| Index: src/builtins.cc
|
| diff --git a/src/builtins.cc b/src/builtins.cc
|
| index ae07df23cbc6bbf4f5eec43268608c8bd67aaa4c..5fd258a605b5fb6c3d3e313fb241f71d8a25dc68 100644
|
| --- a/src/builtins.cc
|
| +++ b/src/builtins.cc
|
| @@ -238,55 +238,57 @@ inline bool IsJSArrayFastElementMovingAllowed(Isolate* isolate,
|
| return PrototypeHasNoElements(&iter);
|
| }
|
|
|
| -
|
| -// Returns empty handle if not applicable.
|
| +// Returns |false| if not applicable.
|
| MUST_USE_RESULT
|
| -inline MaybeHandle<FixedArrayBase> EnsureJSArrayWithWritableFastElements(
|
| - Isolate* isolate, Handle<Object> receiver, Arguments* args,
|
| - int first_added_arg) {
|
| - // We explicitly add a HandleScope to avoid creating several copies of the
|
| - // same handle which would otherwise cause issue when left-trimming later-on.
|
| - HandleScope scope(isolate);
|
| - if (!receiver->IsJSArray()) return MaybeHandle<FixedArrayBase>();
|
| +inline bool EnsureJSArrayWithWritableFastElements(Isolate* isolate,
|
| + Handle<Object> receiver,
|
| + Arguments* args,
|
| + int first_added_arg) {
|
| + if (!receiver->IsJSArray()) return false;
|
| 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)) {
|
| - return MaybeHandle<FixedArrayBase>();
|
| + return false;
|
| }
|
| - if (array->map()->is_observed()) return MaybeHandle<FixedArrayBase>();
|
| - if (!array->map()->is_extensible()) return MaybeHandle<FixedArrayBase>();
|
| - Handle<FixedArrayBase> elms(array->elements(), isolate);
|
| - Map* map = elms->map();
|
| + 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 scope.CloseAndEscape(elms);
|
| + return true;
|
| }
|
| } else if (map == heap->fixed_cow_array_map()) {
|
| - elms = JSObject::EnsureWritableFastElements(array);
|
| + // 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 scope.CloseAndEscape(elms);
|
| + return true;
|
| }
|
| } else if (map == heap->fixed_double_array_map()) {
|
| if (args == NULL) {
|
| - return scope.CloseAndEscape(elms);
|
| + return true;
|
| }
|
| } else {
|
| - return MaybeHandle<FixedArrayBase>();
|
| + return false;
|
| }
|
|
|
| // Adding elements to the array prototype would break code that makes sure
|
| // it has no elements. Handle that elsewhere.
|
| if (isolate->IsAnyInitialArrayPrototype(array)) {
|
| - return MaybeHandle<FixedArrayBase>();
|
| + 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 scope.CloseAndEscape(elms);
|
| + return true;
|
| }
|
|
|
| ElementsKind origin_kind = array->map()->elements_kind();
|
| @@ -309,10 +311,12 @@ inline MaybeHandle<FixedArrayBase> EnsureJSArrayWithWritableFastElements(
|
| }
|
| }
|
| if (target_kind != origin_kind) {
|
| + // 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);
|
| JSObject::TransitionElementsKind(array, target_kind);
|
| - elms = handle(array->elements(), isolate);
|
| }
|
| - return scope.CloseAndEscape(elms);
|
| + return true;
|
| }
|
|
|
|
|
| @@ -352,10 +356,7 @@ BUILTIN(EmptyFunction) { return isolate->heap()->undefined_value(); }
|
| BUILTIN(ArrayPush) {
|
| HandleScope scope(isolate);
|
| Handle<Object> receiver = args.receiver();
|
| - MaybeHandle<FixedArrayBase> maybe_elms_obj =
|
| - EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1);
|
| - Handle<FixedArrayBase> elms_obj;
|
| - if (!maybe_elms_obj.ToHandle(&elms_obj)) {
|
| + if (!EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1)) {
|
| return CallJsIntrinsic(isolate, isolate->array_push(), args);
|
| }
|
| // Fast Elements Path
|
| @@ -365,13 +366,14 @@ BUILTIN(ArrayPush) {
|
| if (push_size == 0) {
|
| return Smi::FromInt(len);
|
| }
|
| - if (push_size > 0 &&
|
| - JSArray::WouldChangeReadOnlyLength(array, len + push_size)) {
|
| + DCHECK(push_size > 0);
|
| + 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, elms_obj, &args, push_size);
|
| + int new_length = accessor->Push(array, handle(array->elements(), isolate),
|
| + &args, push_size);
|
| return Smi::FromInt(new_length);
|
| }
|
|
|
| @@ -379,10 +381,7 @@ BUILTIN(ArrayPush) {
|
| BUILTIN(ArrayPop) {
|
| HandleScope scope(isolate);
|
| Handle<Object> receiver = args.receiver();
|
| - MaybeHandle<FixedArrayBase> maybe_elms_obj =
|
| - EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0);
|
| - Handle<FixedArrayBase> elms_obj;
|
| - if (!maybe_elms_obj.ToHandle(&elms_obj)) {
|
| + if (!EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0)) {
|
| return CallJsIntrinsic(isolate, isolate->array_pop(), args);
|
| }
|
|
|
| @@ -399,7 +398,8 @@ BUILTIN(ArrayPop) {
|
| Handle<Object> result;
|
| if (IsJSArrayFastElementMovingAllowed(isolate, JSArray::cast(*receiver))) {
|
| // Fast Elements Path
|
| - result = array->GetElementsAccessor()->Pop(array, elms_obj);
|
| + result = array->GetElementsAccessor()->Pop(
|
| + array, handle(array->elements(), isolate));
|
| } else {
|
| // Use Slow Lookup otherwise
|
| uint32_t new_length = len - 1;
|
| @@ -415,10 +415,7 @@ BUILTIN(ArrayShift) {
|
| HandleScope scope(isolate);
|
| Heap* heap = isolate->heap();
|
| Handle<Object> receiver = args.receiver();
|
| - MaybeHandle<FixedArrayBase> maybe_elms_obj =
|
| - EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0);
|
| - Handle<FixedArrayBase> elms_obj;
|
| - if (!maybe_elms_obj.ToHandle(&elms_obj) ||
|
| + if (!EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0) ||
|
| !IsJSArrayFastElementMovingAllowed(isolate, JSArray::cast(*receiver))) {
|
| return CallJsIntrinsic(isolate, isolate->array_shift(), args);
|
| }
|
| @@ -432,7 +429,8 @@ BUILTIN(ArrayShift) {
|
| return CallJsIntrinsic(isolate, isolate->array_shift(), args);
|
| }
|
|
|
| - Handle<Object> first = array->GetElementsAccessor()->Shift(array, elms_obj);
|
| + Handle<Object> first = array->GetElementsAccessor()->Shift(
|
| + array, handle(array->elements(), isolate));
|
| return *first;
|
| }
|
|
|
| @@ -440,10 +438,7 @@ BUILTIN(ArrayShift) {
|
| BUILTIN(ArrayUnshift) {
|
| HandleScope scope(isolate);
|
| Handle<Object> receiver = args.receiver();
|
| - MaybeHandle<FixedArrayBase> maybe_elms_obj =
|
| - EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1);
|
| - Handle<FixedArrayBase> elms_obj;
|
| - if (!maybe_elms_obj.ToHandle(&elms_obj)) {
|
| + if (!EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1)) {
|
| return CallJsIntrinsic(isolate, isolate->array_unshift(), args);
|
| }
|
| Handle<JSArray> array = Handle<JSArray>::cast(receiver);
|
| @@ -461,7 +456,8 @@ BUILTIN(ArrayUnshift) {
|
| }
|
|
|
| ElementsAccessor* accessor = array->GetElementsAccessor();
|
| - int new_length = accessor->Unshift(array, elms_obj, &args, to_add);
|
| + int new_length = accessor->Unshift(array, handle(array->elements(), isolate),
|
| + &args, to_add);
|
| return Smi::FromInt(new_length);
|
| }
|
|
|
| @@ -558,13 +554,10 @@ BUILTIN(ArraySlice) {
|
| BUILTIN(ArraySplice) {
|
| HandleScope scope(isolate);
|
| Handle<Object> receiver = args.receiver();
|
| - MaybeHandle<FixedArrayBase> maybe_elms_obj =
|
| - EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 3);
|
| - Handle<FixedArrayBase> elms_obj;
|
| - if (!maybe_elms_obj.ToHandle(&elms_obj) ||
|
| - // If this is a subclass of Array, then call out to JS
|
| + if (!EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 3) ||
|
| + // If this is a subclass of Array, then call out to JS.
|
| !JSArray::cast(*receiver)->map()->new_target_is_base() ||
|
| - // If anything with @@species has been messed with, call out to JS
|
| + // If anything with @@species has been messed with, call out to JS.
|
| !isolate->IsArraySpeciesLookupChainIntact()) {
|
| return CallJsIntrinsic(isolate, isolate->array_splice(), args);
|
| }
|
| @@ -613,8 +606,9 @@ BUILTIN(ArraySplice) {
|
| return CallJsIntrinsic(isolate, isolate->array_splice(), args);
|
| }
|
| ElementsAccessor* accessor = array->GetElementsAccessor();
|
| - Handle<JSArray> result_array = accessor->Splice(
|
| - array, elms_obj, actual_start, actual_delete_count, &args, add_count);
|
| + Handle<JSArray> result_array =
|
| + accessor->Splice(array, handle(array->elements(), isolate), actual_start,
|
| + actual_delete_count, &args, add_count);
|
| return *result_array;
|
| }
|
|
|
|
|