Chromium Code Reviews| Index: src/runtime/runtime-array.cc |
| diff --git a/src/runtime/runtime-array.cc b/src/runtime/runtime-array.cc |
| index a92215c85d046ab8121dab8248d336c96e55fe15..8599f55186a06170792a35d205d9dccb23364aee 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; |
| } |
| @@ -438,5 +445,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()); |
| + if (result.FromJust()) { |
| + return isolate->heap()->true_value(); |
| + } else { |
| + return isolate->heap()->false_value(); |
| + } |
|
Camillo Bruni
2016/07/21 08:01:55
nit: isolate->heap()->ToBoolean(result.FromJust())
|
| +} |
| + |
| +// ES7 22.1.3.11 Array.prototype.includes |
| +RUNTIME_FUNCTION(Runtime_ArrayIncludes_Slow) { |
| + HandleScope shs(isolate); |
|
Camillo Bruni
2016/07/21 08:01:55
uber-nit: shs => sh (it's not a SealedHandleScope)
|
| + DCHECK(args.length() == 3); |
|
Camillo Bruni
2016/07/21 08:01:55
nit: DCHECK_EQ
|
| + CONVERT_ARG_HANDLE_CHECKED(Object, search_element, 1); |
| + CONVERT_ARG_HANDLE_CHECKED(Object, from_index_, 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")). |
|
Camillo Bruni
2016/07/21 08:01:55
Maybe add a shortcut for JS_ARRAY instance types d
|
| + Handle<Object> len_; |
| + Handle<String> length_string = |
| + handle(isolate->heap()->length_string(), isolate); |
|
Camillo Bruni
2016/07/21 08:01:55
nit: isolate->factory()->length_string() returns d
|
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| + isolate, len_, Object::GetProperty(object, length_string)); |
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, len_, |
| + Object::ToLength(isolate, len_)); |
| + int64_t 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, from_index_, |
| + Object::ToInteger(isolate, from_index_)); |
| + if (std::isinf(from_index_->Number()) && from_index_->Number() > 0.0) { |
| + return isolate->heap()->false_value(); |
| + } |
| + int64_t from_index = static_cast<int64_t>(from_index_->Number()); |
| + |
| + int64_t k; |
|
Camillo Bruni
2016/07/21 08:01:55
nit: despite the spec, can you give reasonable var
caitp
2016/07/21 20:32:29
Done.
|
| + if (from_index >= 0) { |
| + k = from_index; |
| + } else { |
| + k = len + from_index; |
| + if (k < 0) { |
| + k = 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>(k), |
| + static_cast<uint32_t>(len)); |
| + } |
| + |
| + // Otherwise, perform slow lookups for JSProxies and API objects, or for |
| + // objects with long `length` values. |
| + for (; k < len; ++k) { |
| + Handle<Object> element_k; |
| + |
| + Handle<Object> index = isolate->factory()->NewNumberFromInt64(k); |
| + |
| + bool success; |
| + LookupIterator it = |
| + LookupIterator::PropertyOrElement(isolate, object, index, &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 |