Index: src/runtime/runtime-array.cc |
diff --git a/src/runtime/runtime-array.cc b/src/runtime/runtime-array.cc |
index 6664c814006798046ef7a6ffa279788e04146a49..f6c6e9d6f27486eceabfb89ce0ddb30a775b0166 100644 |
--- a/src/runtime/runtime-array.cc |
+++ b/src/runtime/runtime-array.cc |
@@ -32,18 +32,24 @@ RUNTIME_FUNCTION(Runtime_FinishArrayPrototypeSetup) { |
} |
static void InstallCode(Isolate* isolate, Handle<JSObject> holder, |
- const char* name, Handle<Code> code) { |
+ const char* name, Handle<Code> code, int argc = -1) { |
Handle<String> key = isolate->factory()->InternalizeUtf8String(name); |
Handle<JSFunction> optimized = |
isolate->factory()->NewFunctionWithoutPrototype(key, code); |
- optimized->shared()->DontAdaptArguments(); |
+ if (argc < 0) { |
+ optimized->shared()->DontAdaptArguments(); |
+ } else { |
+ optimized->shared()->set_internal_formal_parameter_count(argc); |
+ } |
JSObject::AddProperty(holder, key, optimized, NONE); |
} |
static void InstallBuiltin(Isolate* isolate, Handle<JSObject> holder, |
- const char* name, Builtins::Name builtin_name) { |
+ const char* name, Builtins::Name builtin_name, |
+ int argc = -1) { |
InstallCode(isolate, holder, name, |
- handle(isolate->builtins()->builtin(builtin_name), isolate)); |
+ handle(isolate->builtins()->builtin(builtin_name), isolate), |
+ argc); |
} |
RUNTIME_FUNCTION(Runtime_SpecialArrayFunctions) { |
@@ -59,6 +65,7 @@ RUNTIME_FUNCTION(Runtime_SpecialArrayFunctions) { |
InstallBuiltin(isolate, holder, "unshift", Builtins::kArrayUnshift); |
InstallBuiltin(isolate, holder, "slice", Builtins::kArraySlice); |
InstallBuiltin(isolate, holder, "splice", Builtins::kArraySplice); |
+ InstallBuiltin(isolate, holder, "includes", Builtins::kArrayIncludes, 2); |
return *holder; |
} |
@@ -439,5 +446,100 @@ RUNTIME_FUNCTION(Runtime_ArraySpeciesConstructor) { |
isolate, Object::ArraySpeciesConstructor(isolate, original_array)); |
} |
+static inline Object* FastArrayIncludes(Isolate* isolate, |
+ Handle<JSObject> object, |
+ Handle<Object> value, uint32_t k, |
+ uint32_t len) { |
+ ElementsAccessor* elements = object->GetElementsAccessor(); |
+ Maybe<bool> result = elements->IncludesValue(isolate, object, value, k, len); |
+ MAYBE_RETURN(result, isolate->heap()->exception()); |
+ return *isolate->factory()->ToBoolean(result.FromJust()); |
+} |
+ |
+// ES7 22.1.3.11 Array.prototype.includes |
+RUNTIME_FUNCTION(Runtime_ArrayIncludes_Slow) { |
+ HandleScope shs(isolate); |
+ DCHECK(args.length() == 3); |
+ CONVERT_ARG_HANDLE_CHECKED(Object, search_element, 1); |
+ CONVERT_ARG_HANDLE_CHECKED(Object, start_from_, 2); |
+ |
+ // 1. Let O be ? ToObject(this value). |
+ Handle<JSReceiver> object; |
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
+ isolate, object, Object::ToObject(isolate, handle(args[0], isolate))); |
+ |
+ // 2. Let len be ? ToLength(? Get(O, "length")). |
+ Handle<Object> len_; |
+ int64_t len; |
+ if (object->map()->instance_type() == JS_ARRAY_TYPE) { |
+ len_ = handle(JSArray::cast(*object)->length(), isolate); |
+ } else { |
+ 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()); |
+ |
+ // 3. If len is 0, return false. |
+ if (len == 0) return isolate->heap()->false_value(); |
+ |
+ // 4. Let n be ? ToInteger(fromIndex). (If fromIndex is undefined, |
+ // this step produces the value 0.) |
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, start_from_, |
+ Object::ToInteger(isolate, start_from_)); |
+ if (std::isinf(start_from_->Number()) && start_from_->Number() > 0.0) { |
+ return isolate->heap()->false_value(); |
+ } |
+ int64_t start_from = static_cast<int64_t>(start_from_->Number()); |
+ |
+ int64_t index; |
+ if (start_from >= 0) { |
+ index = start_from; |
+ } else { |
+ index = len + start_from; |
+ if (index < 0) { |
+ index = 0; |
+ } |
+ } |
+ |
+ // In the slow path, we can still take a fast path similar to the TurboFan |
+ // implementation if there are no elements in the prototype, and if the length |
+ // is within elements boundaries. |
+ // |
+ // This would apply to Array-like Objects with no elements in the prototype, |
+ // for example. |
+ if (object->map()->instance_type() > LAST_SPECIAL_RECEIVER_TYPE && |
+ len < std::numeric_limits<uint32_t>::max() && |
+ JSObject::PrototypeHasNoElements(isolate, JSObject::cast(*object))) { |
+ return FastArrayIncludes(isolate, Handle<JSObject>::cast(object), |
+ search_element, static_cast<uint32_t>(index), |
+ static_cast<uint32_t>(len)); |
+ } |
+ |
+ // Otherwise, perform slow lookups for JSProxies and API objects, or for |
+ // objects with long `length` values. |
+ for (; index < len; ++index) { |
+ Handle<Object> element_k; |
+ |
+ Handle<Object> index_object = isolate->factory()->NewNumberFromInt64(index); |
+ |
+ bool success; |
+ LookupIterator it = LookupIterator::PropertyOrElement( |
+ isolate, object, index_object, &success); |
+ DCHECK(success); |
+ |
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, element_k, |
+ Object::GetProperty(&it)); |
+ |
+ if (search_element->SameValueZero(*element_k)) { |
+ return isolate->heap()->true_value(); |
+ } |
+ } |
+ return isolate->heap()->false_value(); |
+} |
+ |
} // namespace internal |
} // namespace v8 |