| Index: src/builtins.cc
|
| diff --git a/src/builtins.cc b/src/builtins.cc
|
| index 18f398d7d6192fdb8f9ed8a90f60309dbaa4e5bc..a85edc834251da617f2d8170cd9ba42b119f39bb 100644
|
| --- a/src/builtins.cc
|
| +++ b/src/builtins.cc
|
| @@ -248,51 +248,25 @@ inline bool EnsureJSArrayWithWritableFastElements(Isolate* isolate,
|
| Handle<JSArray> array = Handle<JSArray>::cast(receiver);
|
| // If there may be elements accessors in the prototype chain, the fast path
|
| // cannot be used if there arguments to add to the array.
|
| - Heap* heap = isolate->heap();
|
| - if (args != NULL && !IsJSArrayFastElementMovingAllowed(isolate, *array)) {
|
| + if (args != nullptr && !IsJSArrayFastElementMovingAllowed(isolate, *array)) {
|
| return false;
|
| }
|
| + ElementsKind origin_kind = array->map()->elements_kind();
|
| + if (IsDictionaryElementsKind(origin_kind)) return false;
|
| if (array->map()->is_observed()) return false;
|
| if (!array->map()->is_extensible()) return false;
|
| - Map* map = array->elements()->map();
|
| - if (map == heap->fixed_array_map()) {
|
| - if (args == NULL || array->HasFastObjectElements()) {
|
| - return true;
|
| - }
|
| - } else if (map == heap->fixed_cow_array_map()) {
|
| - // Use a short-lived HandleScope to avoid creating several copies of the
|
| - // elements handle which would cause issues when left-trimming later-on.
|
| - HandleScope scope(isolate);
|
| - // TODO(jkummerow/verwaest): Move this call (or this entire function?)
|
| - // into the ElementsAccessor so it's only done when needed (e.g. ArrayPush
|
| - // can skip it because it must grow the backing store anyway).
|
| - JSObject::EnsureWritableFastElements(array);
|
| - if (args == NULL || array->HasFastObjectElements()) {
|
| - return true;
|
| - }
|
| - } else if (map == heap->fixed_double_array_map()) {
|
| - if (args == NULL) {
|
| - return true;
|
| - }
|
| - } else {
|
| - return false;
|
| - }
|
| + if (args == nullptr) return true;
|
|
|
| // Adding elements to the array prototype would break code that makes sure
|
| // it has no elements. Handle that elsewhere.
|
| - if (isolate->IsAnyInitialArrayPrototype(array)) {
|
| - return false;
|
| - }
|
| + if (isolate->IsAnyInitialArrayPrototype(array)) return false;
|
|
|
| // Need to ensure that the arguments passed in args can be contained in
|
| // the array.
|
| int args_length = args->length();
|
| - if (first_added_arg >= args_length) {
|
| - return true;
|
| - }
|
| + if (first_added_arg >= args_length) return true;
|
|
|
| - ElementsKind origin_kind = array->map()->elements_kind();
|
| - DCHECK(!IsFastObjectElementsKind(origin_kind));
|
| + if (IsFastObjectElementsKind(origin_kind)) return true;
|
| ElementsKind target_kind = origin_kind;
|
| {
|
| DisallowHeapAllocation no_gc;
|
| @@ -437,20 +411,20 @@ BUILTIN(ArrayPush) {
|
| return CallJsIntrinsic(isolate, isolate->array_push(), args);
|
| }
|
| // Fast Elements Path
|
| - int push_size = args.length() - 1;
|
| + int to_add = args.length() - 1;
|
| Handle<JSArray> array = Handle<JSArray>::cast(receiver);
|
| int len = Smi::cast(array->length())->value();
|
| - if (push_size == 0) {
|
| - return Smi::FromInt(len);
|
| - }
|
| - DCHECK(push_size > 0);
|
| + if (to_add == 0) return Smi::FromInt(len);
|
| +
|
| + // Currently fixed arrays cannot grow too big, so we should never hit this.
|
| + DCHECK_LE(to_add, Smi::kMaxValue - Smi::cast(array->length())->value());
|
| +
|
| if (JSArray::HasReadOnlyLength(array)) {
|
| return CallJsIntrinsic(isolate, isolate->array_push(), args);
|
| }
|
| - DCHECK(!array->map()->is_observed());
|
| +
|
| ElementsAccessor* accessor = array->GetElementsAccessor();
|
| - int new_length = accessor->Push(array, handle(array->elements(), isolate),
|
| - &args, push_size);
|
| + int new_length = accessor->Push(array, &args, to_add);
|
| return Smi::FromInt(new_length);
|
| }
|
|
|
| @@ -458,7 +432,7 @@ BUILTIN(ArrayPush) {
|
| BUILTIN(ArrayPop) {
|
| HandleScope scope(isolate);
|
| Handle<Object> receiver = args.receiver();
|
| - if (!EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0)) {
|
| + if (!EnsureJSArrayWithWritableFastElements(isolate, receiver, nullptr, 0)) {
|
| return CallJsIntrinsic(isolate, isolate->array_pop(), args);
|
| }
|
|
|
| @@ -475,8 +449,7 @@ BUILTIN(ArrayPop) {
|
| Handle<Object> result;
|
| if (IsJSArrayFastElementMovingAllowed(isolate, JSArray::cast(*receiver))) {
|
| // Fast Elements Path
|
| - result = array->GetElementsAccessor()->Pop(
|
| - array, handle(array->elements(), isolate));
|
| + result = array->GetElementsAccessor()->Pop(array);
|
| } else {
|
| // Use Slow Lookup otherwise
|
| uint32_t new_length = len - 1;
|
| @@ -492,7 +465,7 @@ BUILTIN(ArrayShift) {
|
| HandleScope scope(isolate);
|
| Heap* heap = isolate->heap();
|
| Handle<Object> receiver = args.receiver();
|
| - if (!EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0) ||
|
| + if (!EnsureJSArrayWithWritableFastElements(isolate, receiver, nullptr, 0) ||
|
| !IsJSArrayFastElementMovingAllowed(isolate, JSArray::cast(*receiver))) {
|
| return CallJsIntrinsic(isolate, isolate->array_shift(), args);
|
| }
|
| @@ -506,8 +479,7 @@ BUILTIN(ArrayShift) {
|
| return CallJsIntrinsic(isolate, isolate->array_shift(), args);
|
| }
|
|
|
| - Handle<Object> first = array->GetElementsAccessor()->Shift(
|
| - array, handle(array->elements(), isolate));
|
| + Handle<Object> first = array->GetElementsAccessor()->Shift(array);
|
| return *first;
|
| }
|
|
|
| @@ -521,20 +493,17 @@ BUILTIN(ArrayUnshift) {
|
| Handle<JSArray> array = Handle<JSArray>::cast(receiver);
|
| DCHECK(!array->map()->is_observed());
|
| int to_add = args.length() - 1;
|
| - if (to_add == 0) {
|
| - return array->length();
|
| - }
|
| - // Currently fixed arrays cannot grow too big, so
|
| - // we should never hit this case.
|
| - DCHECK(to_add <= (Smi::kMaxValue - Smi::cast(array->length())->value()));
|
| + if (to_add == 0) return array->length();
|
|
|
| - if (to_add > 0 && JSArray::HasReadOnlyLength(array)) {
|
| + // Currently fixed arrays cannot grow too big, so we should never hit this.
|
| + DCHECK_LE(to_add, Smi::kMaxValue - Smi::cast(array->length())->value());
|
| +
|
| + if (JSArray::HasReadOnlyLength(array)) {
|
| return CallJsIntrinsic(isolate, isolate->array_unshift(), args);
|
| }
|
|
|
| ElementsAccessor* accessor = array->GetElementsAccessor();
|
| - int new_length = accessor->Unshift(array, handle(array->elements(), isolate),
|
| - &args, to_add);
|
| + int new_length = accessor->Unshift(array, &args, to_add);
|
| return Smi::FromInt(new_length);
|
| }
|
|
|
| @@ -542,12 +511,9 @@ BUILTIN(ArrayUnshift) {
|
| BUILTIN(ArraySlice) {
|
| HandleScope scope(isolate);
|
| Handle<Object> receiver = args.receiver();
|
| - Handle<JSObject> object;
|
| - Handle<FixedArrayBase> elms_obj;
|
| int len = -1;
|
| int relative_start = 0;
|
| int relative_end = 0;
|
| - bool is_sloppy_arguments = false;
|
|
|
| if (receiver->IsJSArray()) {
|
| DisallowHeapAllocation no_gc;
|
| @@ -561,22 +527,18 @@ BUILTIN(ArraySlice) {
|
| return CallJsIntrinsic(isolate, isolate->array_slice(), args);
|
| }
|
| len = Smi::cast(array->length())->value();
|
| - object = Handle<JSObject>::cast(receiver);
|
| - elms_obj = handle(array->elements(), isolate);
|
| } else if (receiver->IsJSObject() &&
|
| GetSloppyArgumentsLength(isolate, Handle<JSObject>::cast(receiver),
|
| &len)) {
|
| + DCHECK_EQ(FAST_ELEMENTS, JSObject::cast(*receiver)->GetElementsKind());
|
| // Array.prototype.slice(arguments, ...) is quite a common idiom
|
| // (notably more than 50% of invocations in Web apps).
|
| // Treat it in C++ as well.
|
| - is_sloppy_arguments = true;
|
| - object = Handle<JSObject>::cast(receiver);
|
| - elms_obj = handle(object->elements(), isolate);
|
| } else {
|
| AllowHeapAllocation allow_allocation;
|
| return CallJsIntrinsic(isolate, isolate->array_slice(), args);
|
| }
|
| - DCHECK(len >= 0);
|
| + DCHECK_LE(0, len);
|
| int argument_count = args.length() - 1;
|
| // Note carefully chosen defaults---if argument is missing,
|
| // it's undefined which gets converted to 0 for relative_start
|
| @@ -609,22 +571,9 @@ BUILTIN(ArraySlice) {
|
| uint32_t actual_end =
|
| (relative_end < 0) ? Max(len + relative_end, 0) : Min(relative_end, len);
|
|
|
| - if (actual_end <= actual_start) {
|
| - Handle<JSArray> result_array = isolate->factory()->NewJSArray(
|
| - GetPackedElementsKind(object->GetElementsKind()), 0, 0);
|
| - return *result_array;
|
| - }
|
| -
|
| + Handle<JSObject> object = Handle<JSObject>::cast(receiver);
|
| ElementsAccessor* accessor = object->GetElementsAccessor();
|
| - if (is_sloppy_arguments &&
|
| - !accessor->IsPacked(object, elms_obj, actual_start, actual_end)) {
|
| - // Don't deal with arguments with holes in C++
|
| - AllowHeapAllocation allow_allocation;
|
| - return CallJsIntrinsic(isolate, isolate->array_slice(), args);
|
| - }
|
| - Handle<JSArray> result_array =
|
| - accessor->Slice(object, elms_obj, actual_start, actual_end);
|
| - return *result_array;
|
| + return *accessor->Slice(object, actual_start, actual_end);
|
| }
|
|
|
|
|
| @@ -683,9 +632,8 @@ BUILTIN(ArraySplice) {
|
| return CallJsIntrinsic(isolate, isolate->array_splice(), args);
|
| }
|
| ElementsAccessor* accessor = array->GetElementsAccessor();
|
| - Handle<JSArray> result_array =
|
| - accessor->Splice(array, handle(array->elements(), isolate), actual_start,
|
| - actual_delete_count, &args, add_count);
|
| + Handle<JSArray> result_array = accessor->Splice(
|
| + array, actual_start, actual_delete_count, &args, add_count);
|
| return *result_array;
|
| }
|
|
|
|
|