Chromium Code Reviews| Index: src/builtins.cc |
| diff --git a/src/builtins.cc b/src/builtins.cc |
| index dba56372e469814cb5c4652ef01e1d5d660918ee..805537448a6468d10659b611e4ea6f5a987409fd 100644 |
| --- a/src/builtins.cc |
| +++ b/src/builtins.cc |
| @@ -929,7 +929,7 @@ void CollectElementIndices(Handle<JSObject> object, uint32_t range, |
| } |
| -bool IterateElementsSlow(Isolate* isolate, Handle<JSObject> receiver, |
| +bool IterateElementsSlow(Isolate* isolate, Handle<JSReceiver> receiver, |
| uint32_t length, ArrayConcatVisitor* visitor) { |
| for (uint32_t i = 0; i < length; ++i) { |
| HandleScope loop_scope(isolate); |
| @@ -949,7 +949,7 @@ bool IterateElementsSlow(Isolate* isolate, Handle<JSObject> receiver, |
| /** |
| - * A helper function that visits elements of a JSObject in numerical |
| + * A helper function that visits "array" elements of a JSReceiver in numerical |
| * order. |
| * |
| * The visitor argument called for each existing element in the array |
| @@ -958,7 +958,7 @@ bool IterateElementsSlow(Isolate* isolate, Handle<JSObject> receiver, |
| * length. |
| * Returns false if any access threw an exception, otherwise true. |
| */ |
| -bool IterateElements(Isolate* isolate, Handle<JSObject> receiver, |
| +bool IterateElements(Isolate* isolate, Handle<JSReceiver> receiver, |
| ArrayConcatVisitor* visitor) { |
| uint32_t length = 0; |
| @@ -984,15 +984,16 @@ bool IterateElements(Isolate* isolate, Handle<JSObject> receiver, |
| // use the slow case. |
| return IterateElementsSlow(isolate, receiver, length, visitor); |
| } |
| + Handle<JSObject> array = Handle<JSObject>::cast(receiver); |
| - switch (receiver->GetElementsKind()) { |
| + switch (array->GetElementsKind()) { |
| case FAST_SMI_ELEMENTS: |
| case FAST_ELEMENTS: |
| case FAST_HOLEY_SMI_ELEMENTS: |
| case FAST_HOLEY_ELEMENTS: { |
| // Run through the elements FixedArray and use HasElement and GetElement |
| // to check the prototype for missing elements. |
| - Handle<FixedArray> elements(FixedArray::cast(receiver->elements())); |
| + Handle<FixedArray> elements(FixedArray::cast(array->elements())); |
| int fast_length = static_cast<int>(length); |
| DCHECK(fast_length <= elements->length()); |
| for (int j = 0; j < fast_length; j++) { |
| @@ -1001,14 +1002,14 @@ bool IterateElements(Isolate* isolate, Handle<JSObject> receiver, |
| if (!element_value->IsTheHole()) { |
| visitor->visit(j, element_value); |
| } else { |
| - Maybe<bool> maybe = JSReceiver::HasElement(receiver, j); |
| + Maybe<bool> maybe = JSReceiver::HasElement(array, j); |
| if (!maybe.IsJust()) return false; |
| if (maybe.FromJust()) { |
| - // Call GetElement on receiver, not its prototype, or getters won't |
| + // Call GetElement on array, not its prototype, or getters won't |
| // have the correct receiver. |
| ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| - isolate, element_value, |
| - Object::GetElement(isolate, receiver, j), false); |
| + isolate, element_value, Object::GetElement(isolate, array, j), |
| + false); |
| visitor->visit(j, element_value); |
| } |
| } |
| @@ -1021,12 +1022,12 @@ bool IterateElements(Isolate* isolate, Handle<JSObject> receiver, |
| if (length == 0) break; |
| // Run through the elements FixedArray and use HasElement and GetElement |
| // to check the prototype for missing elements. |
| - if (receiver->elements()->IsFixedArray()) { |
| - DCHECK(receiver->elements()->length() == 0); |
| + if (array->elements()->IsFixedArray()) { |
| + DCHECK(array->elements()->length() == 0); |
| break; |
| } |
| Handle<FixedDoubleArray> elements( |
| - FixedDoubleArray::cast(receiver->elements())); |
| + FixedDoubleArray::cast(array->elements())); |
| int fast_length = static_cast<int>(length); |
| DCHECK(fast_length <= elements->length()); |
| for (int j = 0; j < fast_length; j++) { |
| @@ -1037,15 +1038,15 @@ bool IterateElements(Isolate* isolate, Handle<JSObject> receiver, |
| isolate->factory()->NewNumber(double_value); |
| visitor->visit(j, element_value); |
| } else { |
| - Maybe<bool> maybe = JSReceiver::HasElement(receiver, j); |
| + Maybe<bool> maybe = JSReceiver::HasElement(array, j); |
| if (!maybe.IsJust()) return false; |
| if (maybe.FromJust()) { |
| - // Call GetElement on receiver, not its prototype, or getters won't |
| + // Call GetElement on array, not its prototype, or getters won't |
| // have the correct receiver. |
| Handle<Object> element_value; |
| ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| - isolate, element_value, |
| - Object::GetElement(isolate, receiver, j), false); |
| + isolate, element_value, Object::GetElement(isolate, array, j), |
| + false); |
| visitor->visit(j, element_value); |
| } |
| } |
| @@ -1055,17 +1056,17 @@ bool IterateElements(Isolate* isolate, Handle<JSObject> receiver, |
| case DICTIONARY_ELEMENTS: { |
| // CollectElementIndices() can't be called when there's a JSProxy |
| // on the prototype chain. |
| - for (PrototypeIterator iter(isolate, receiver); !iter.IsAtEnd(); |
| + for (PrototypeIterator iter(isolate, array); !iter.IsAtEnd(); |
| iter.Advance()) { |
| if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { |
| - return IterateElementsSlow(isolate, receiver, length, visitor); |
| + return IterateElementsSlow(isolate, array, length, visitor); |
| } |
| } |
| - Handle<SeededNumberDictionary> dict(receiver->element_dictionary()); |
| + Handle<SeededNumberDictionary> dict(array->element_dictionary()); |
| List<uint32_t> indices(dict->Capacity() / 2); |
| // Collect all indices in the object and the prototypes less |
| // than length. This might introduce duplicates in the indices list. |
| - CollectElementIndices(receiver, length, &indices); |
| + CollectElementIndices(array, length, &indices); |
| indices.Sort(&compareUInt32); |
| int j = 0; |
| int n = indices.length(); |
| @@ -1074,8 +1075,7 @@ bool IterateElements(Isolate* isolate, Handle<JSObject> receiver, |
| uint32_t index = indices[j]; |
| Handle<Object> element; |
| ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| - isolate, element, Object::GetElement(isolate, receiver, index), |
| - false); |
| + isolate, element, Object::GetElement(isolate, array, index), false); |
| visitor->visit(index, element); |
| // Skip to next different index (i.e., omit duplicates). |
| do { |
| @@ -1086,7 +1086,7 @@ bool IterateElements(Isolate* isolate, Handle<JSObject> receiver, |
| } |
| case UINT8_CLAMPED_ELEMENTS: { |
| Handle<FixedUint8ClampedArray> pixels( |
| - FixedUint8ClampedArray::cast(receiver->elements())); |
| + FixedUint8ClampedArray::cast(array->elements())); |
| for (uint32_t j = 0; j < length; j++) { |
| Handle<Smi> e(Smi::FromInt(pixels->get_scalar(j)), isolate); |
| visitor->visit(j, e); |
| @@ -1094,43 +1094,43 @@ bool IterateElements(Isolate* isolate, Handle<JSObject> receiver, |
| break; |
| } |
| case INT8_ELEMENTS: { |
| - IterateTypedArrayElements<FixedInt8Array, int8_t>(isolate, receiver, true, |
| + IterateTypedArrayElements<FixedInt8Array, int8_t>(isolate, array, true, |
| true, visitor); |
| break; |
| } |
| case UINT8_ELEMENTS: { |
| - IterateTypedArrayElements<FixedUint8Array, uint8_t>(isolate, receiver, |
| - true, true, visitor); |
| + IterateTypedArrayElements<FixedUint8Array, uint8_t>(isolate, array, true, |
| + true, visitor); |
| break; |
| } |
| case INT16_ELEMENTS: { |
| - IterateTypedArrayElements<FixedInt16Array, int16_t>(isolate, receiver, |
| - true, true, visitor); |
| + IterateTypedArrayElements<FixedInt16Array, int16_t>(isolate, array, true, |
| + true, visitor); |
| break; |
| } |
| case UINT16_ELEMENTS: { |
| IterateTypedArrayElements<FixedUint16Array, uint16_t>( |
| - isolate, receiver, true, true, visitor); |
| + isolate, array, true, true, visitor); |
| break; |
| } |
| case INT32_ELEMENTS: { |
| - IterateTypedArrayElements<FixedInt32Array, int32_t>(isolate, receiver, |
| - true, false, visitor); |
| + IterateTypedArrayElements<FixedInt32Array, int32_t>(isolate, array, true, |
| + false, visitor); |
| break; |
| } |
| case UINT32_ELEMENTS: { |
| IterateTypedArrayElements<FixedUint32Array, uint32_t>( |
| - isolate, receiver, true, false, visitor); |
| + isolate, array, true, false, visitor); |
| break; |
| } |
| case FLOAT32_ELEMENTS: { |
| - IterateTypedArrayElements<FixedFloat32Array, float>( |
| - isolate, receiver, false, false, visitor); |
| + IterateTypedArrayElements<FixedFloat32Array, float>(isolate, array, false, |
| + false, visitor); |
| break; |
| } |
| case FLOAT64_ELEMENTS: { |
| IterateTypedArrayElements<FixedFloat64Array, double>( |
| - isolate, receiver, false, false, visitor); |
| + isolate, array, false, false, visitor); |
| break; |
| } |
| case FAST_SLOPPY_ARGUMENTS_ELEMENTS: |
| @@ -1139,8 +1139,7 @@ bool IterateElements(Isolate* isolate, Handle<JSObject> receiver, |
| HandleScope loop_scope(isolate); |
| Handle<Object> element; |
| ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| - isolate, element, Object::GetElement(isolate, receiver, index), |
| - false); |
| + isolate, element, Object::GetElement(isolate, array, index), false); |
| visitor->visit(index, element); |
| } |
| break; |
| @@ -1152,37 +1151,29 @@ bool IterateElements(Isolate* isolate, Handle<JSObject> receiver, |
| bool HasConcatSpreadableModifier(Isolate* isolate, Handle<JSArray> obj) { |
| + DCHECK(isolate->IsFastArrayConstructorPrototypeChainIntact()); |
|
Camillo Bruni
2015/12/15 16:23:19
I don't think this is needed here since you do a f
neis
2015/12/15 16:25:02
It's important that this Has cannot be observed by
|
| if (!FLAG_harmony_concat_spreadable) return false; |
| Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol()); |
| - Maybe<bool> maybe = |
| - JSReceiver::HasProperty(Handle<JSReceiver>::cast(obj), key); |
| - if (!maybe.IsJust()) return false; |
| - return maybe.FromJust(); |
| + Maybe<bool> maybe = JSReceiver::HasProperty(obj, key); |
| + return maybe.FromMaybe(false); |
| } |
| -bool IsConcatSpreadable(Isolate* isolate, Handle<Object> obj) { |
| +static Maybe<bool> IsConcatSpreadable(Isolate* isolate, Handle<Object> obj) { |
| HandleScope handle_scope(isolate); |
| - if (!obj->IsJSReceiver()) return false; |
| + if (!obj->IsJSReceiver()) return Just(false); |
| if (FLAG_harmony_concat_spreadable) { |
| Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol()); |
| Handle<Object> value; |
| MaybeHandle<Object> maybeValue = |
| i::Runtime::GetObjectProperty(isolate, obj, key); |
| - if (maybeValue.ToHandle(&value) && !value->IsUndefined()) { |
| - return value->BooleanValue(); |
| - } |
| + if (!maybeValue.ToHandle(&value)) return Nothing<bool>(); |
| + if (!value->IsUndefined()) return Just(value->BooleanValue()); |
| } |
| - return obj->IsJSArray(); |
| + return Object::IsArray(obj); |
| } |
| -/** |
| - * Array::concat implementation. |
| - * See ECMAScript 262, 15.4.4.4. |
| - * TODO(581): Fix non-compliance for very large concatenations and update to |
| - * following the ECMAScript 5 specification. |
| - */ |
| Object* Slow_ArrayConcat(Arguments* args, Isolate* isolate) { |
| int argument_count = args->length(); |
| @@ -1338,10 +1329,10 @@ Object* Slow_ArrayConcat(Arguments* args, Isolate* isolate) { |
| for (int i = 0; i < argument_count; i++) { |
| Handle<Object> obj((*args)[i], isolate); |
| - bool spreadable = IsConcatSpreadable(isolate, obj); |
| - if (isolate->has_pending_exception()) return isolate->heap()->exception(); |
| - if (spreadable) { |
| - Handle<JSObject> object = Handle<JSObject>::cast(obj); |
| + Maybe<bool> spreadable = IsConcatSpreadable(isolate, obj); |
| + MAYBE_RETURN(spreadable, isolate->heap()->exception()); |
| + if (spreadable.FromJust()) { |
| + Handle<JSReceiver> object = Handle<JSReceiver>::cast(obj); |
| if (!IterateElements(isolate, object, &visitor)) { |
| return isolate->heap()->exception(); |
| } |
| @@ -1401,6 +1392,7 @@ MaybeHandle<JSArray> Fast_ArrayConcat(Isolate* isolate, Arguments* args) { |
| } // namespace |
| +// ES6 22.1.3.1 Array.prototype.concat |
| BUILTIN(ArrayConcat) { |
| HandleScope scope(isolate); |
| @@ -1423,7 +1415,7 @@ BUILTIN(ArrayConcat) { |
| } |
| -// ES6 section 22.1.2.2 Array.isArray |
| +// ES6 22.1.2.2 Array.isArray |
| BUILTIN(ArrayIsArray) { |
| HandleScope scope(isolate); |
| DCHECK_EQ(2, args.length()); |