| Index: src/builtins.cc
|
| diff --git a/src/builtins.cc b/src/builtins.cc
|
| index 200f7fed632619b30f0011dc8bbbac118c34196d..6dfa04924c0b835203666ab4266e9bf251189bab 100644
|
| --- a/src/builtins.cc
|
| +++ b/src/builtins.cc
|
| @@ -302,7 +302,7 @@ static inline Handle<FixedArrayBase> EnsureJSArrayWithWritableFastElements(
|
| Handle<JSArray> array = Handle<JSArray>::cast(receiver);
|
| if (array->map()->is_observed()) return Handle<FixedArrayBase>::null();
|
| if (!array->map()->is_extensible()) return Handle<FixedArrayBase>::null();
|
| - Handle<FixedArrayBase> elms(array->elements());
|
| + Handle<FixedArrayBase> elms(array->elements(), isolate);
|
| Heap* heap = isolate->heap();
|
| Map* map = elms->map();
|
| if (map == heap->fixed_array_map()) {
|
| @@ -319,7 +319,7 @@ static inline Handle<FixedArrayBase> EnsureJSArrayWithWritableFastElements(
|
| // 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 handle(array->elements());
|
| + if (first_added_arg >= args_length) return handle(array->elements(), isolate);
|
|
|
| ElementsKind origin_kind = array->map()->elements_kind();
|
| ASSERT(!IsFastObjectElementsKind(origin_kind));
|
| @@ -339,7 +339,7 @@ static inline Handle<FixedArrayBase> EnsureJSArrayWithWritableFastElements(
|
| }
|
| if (target_kind != origin_kind) {
|
| JSObject::TransitionElementsKind(array, target_kind);
|
| - return handle(array->elements());
|
| + return handle(array->elements(), isolate);
|
| }
|
| return elms;
|
| }
|
| @@ -418,8 +418,8 @@ BUILTIN(ArrayPush) {
|
|
|
| ElementsAccessor* accessor = array->GetElementsAccessor();
|
| accessor->CopyElements(
|
| - Handle<JSObject>::null(), 0, kind, new_elms, 0,
|
| - ElementsAccessor::kCopyToEndAndInitializeToHole, elms_obj);
|
| + elms_obj, 0, kind, new_elms, 0,
|
| + ElementsAccessor::kCopyToEndAndInitializeToHole);
|
|
|
| elms = new_elms;
|
| }
|
| @@ -461,8 +461,8 @@ BUILTIN(ArrayPush) {
|
|
|
| ElementsAccessor* accessor = array->GetElementsAccessor();
|
| accessor->CopyElements(
|
| - Handle<JSObject>::null(), 0, kind, new_elms, 0,
|
| - ElementsAccessor::kCopyToEndAndInitializeToHole, elms_obj);
|
| + elms_obj, 0, kind, new_elms, 0,
|
| + ElementsAccessor::kCopyToEndAndInitializeToHole);
|
|
|
| } else {
|
| // to_add is > 0 and new_length <= elms_len, so elms_obj cannot be the
|
| @@ -489,18 +489,6 @@ BUILTIN(ArrayPush) {
|
| }
|
|
|
|
|
| -// TODO(ishell): Temporary wrapper until handlified.
|
| -static bool ElementsAccessorHasElementWrapper(
|
| - ElementsAccessor* accessor,
|
| - Handle<Object> receiver,
|
| - Handle<JSObject> holder,
|
| - uint32_t key,
|
| - Handle<FixedArrayBase> backing_store = Handle<FixedArrayBase>::null()) {
|
| - return accessor->HasElement(*receiver, *holder, key,
|
| - backing_store.is_null() ? NULL : *backing_store);
|
| -}
|
| -
|
| -
|
| BUILTIN(ArrayPop) {
|
| HandleScope scope(isolate);
|
| Handle<Object> receiver = args.receiver();
|
| @@ -517,8 +505,7 @@ BUILTIN(ArrayPop) {
|
| ElementsAccessor* accessor = array->GetElementsAccessor();
|
| int new_length = len - 1;
|
| Handle<Object> element;
|
| - if (ElementsAccessorHasElementWrapper(
|
| - accessor, array, array, new_length, elms_obj)) {
|
| + if (accessor->HasElement(*array, *array, new_length, *elms_obj)) {
|
| element = accessor->Get(
|
| array, array, new_length, elms_obj);
|
| } else {
|
| @@ -618,8 +605,8 @@ BUILTIN(ArrayUnshift) {
|
| ElementsKind kind = array->GetElementsKind();
|
| ElementsAccessor* accessor = array->GetElementsAccessor();
|
| accessor->CopyElements(
|
| - Handle<JSObject>::null(), 0, kind, new_elms, to_add,
|
| - ElementsAccessor::kCopyToEndAndInitializeToHole, elms);
|
| + elms, 0, kind, new_elms, to_add,
|
| + ElementsAccessor::kCopyToEndAndInitializeToHole);
|
|
|
| elms = new_elms;
|
| array->set_elements(*elms);
|
| @@ -645,87 +632,95 @@ BUILTIN(ArraySlice) {
|
| HandleScope scope(isolate);
|
| Heap* heap = isolate->heap();
|
| Handle<Object> receiver = args.receiver();
|
| - Handle<FixedArrayBase> elms;
|
| int len = -1;
|
| - if (receiver->IsJSArray()) {
|
| - Handle<JSArray> array = Handle<JSArray>::cast(receiver);
|
| - if (!IsJSArrayFastElementMovingAllowed(heap, *array)) {
|
| - return CallJsBuiltin(isolate, "ArraySlice", args);
|
| - }
|
| -
|
| - if (array->HasFastElements()) {
|
| - elms = handle(array->elements());
|
| - } else {
|
| - return CallJsBuiltin(isolate, "ArraySlice", args);
|
| - }
|
| + int relative_start = 0;
|
| + int relative_end = 0;
|
| + {
|
| + DisallowHeapAllocation no_gc;
|
| + if (receiver->IsJSArray()) {
|
| + JSArray* array = JSArray::cast(*receiver);
|
| + if (!IsJSArrayFastElementMovingAllowed(heap, array)) {
|
| + AllowHeapAllocation allow_allocation;
|
| + return CallJsBuiltin(isolate, "ArraySlice", args);
|
| + }
|
|
|
| - len = Smi::cast(array->length())->value();
|
| - } else {
|
| - // Array.slice(arguments, ...) is quite a common idiom (notably more
|
| - // than 50% of invocations in Web apps). Treat it in C++ as well.
|
| - Handle<Map> arguments_map(isolate->context()->native_context()->
|
| - sloppy_arguments_boilerplate()->map());
|
| -
|
| - bool is_arguments_object_with_fast_elements =
|
| - receiver->IsJSObject() &&
|
| - Handle<JSObject>::cast(receiver)->map() == *arguments_map;
|
| - if (!is_arguments_object_with_fast_elements) {
|
| - return CallJsBuiltin(isolate, "ArraySlice", args);
|
| - }
|
| - Handle<JSObject> object = Handle<JSObject>::cast(receiver);
|
| + if (!array->HasFastElements()) {
|
| + AllowHeapAllocation allow_allocation;
|
| + return CallJsBuiltin(isolate, "ArraySlice", args);
|
| + }
|
|
|
| - if (object->HasFastElements()) {
|
| - elms = handle(object->elements());
|
| + len = Smi::cast(array->length())->value();
|
| } else {
|
| - return CallJsBuiltin(isolate, "ArraySlice", args);
|
| - }
|
| - Handle<Object> len_obj(
|
| - object->InObjectPropertyAt(Heap::kArgumentsLengthIndex), isolate);
|
| - if (!len_obj->IsSmi()) {
|
| - return CallJsBuiltin(isolate, "ArraySlice", args);
|
| - }
|
| - len = Handle<Smi>::cast(len_obj)->value();
|
| - if (len > elms->length()) {
|
| - return CallJsBuiltin(isolate, "ArraySlice", args);
|
| - }
|
| - }
|
| -
|
| - Handle<JSObject> object = Handle<JSObject>::cast(receiver);
|
| + // Array.slice(arguments, ...) is quite a common idiom (notably more
|
| + // than 50% of invocations in Web apps). Treat it in C++ as well.
|
| + Map* arguments_map = isolate->context()->native_context()->
|
| + sloppy_arguments_boilerplate()->map();
|
| +
|
| + bool is_arguments_object_with_fast_elements =
|
| + receiver->IsJSObject() &&
|
| + JSObject::cast(*receiver)->map() == arguments_map;
|
| + if (!is_arguments_object_with_fast_elements) {
|
| + AllowHeapAllocation allow_allocation;
|
| + return CallJsBuiltin(isolate, "ArraySlice", args);
|
| + }
|
| + JSObject* object = JSObject::cast(*receiver);
|
|
|
| - ASSERT(len >= 0);
|
| - int n_arguments = args.length() - 1;
|
| + if (!object->HasFastElements()) {
|
| + AllowHeapAllocation allow_allocation;
|
| + return CallJsBuiltin(isolate, "ArraySlice", args);
|
| + }
|
|
|
| - // Note carefully choosen defaults---if argument is missing,
|
| - // it's undefined which gets converted to 0 for relative_start
|
| - // and to len for relative_end.
|
| - int relative_start = 0;
|
| - int relative_end = len;
|
| - if (n_arguments > 0) {
|
| - Handle<Object> arg1 = args.at<Object>(1);
|
| - if (arg1->IsSmi()) {
|
| - relative_start = Handle<Smi>::cast(arg1)->value();
|
| - } else if (arg1->IsHeapNumber()) {
|
| - double start = Handle<HeapNumber>::cast(arg1)->value();
|
| - if (start < kMinInt || start > kMaxInt) {
|
| + Object* len_obj = object->InObjectPropertyAt(Heap::kArgumentsLengthIndex);
|
| + if (!len_obj->IsSmi()) {
|
| + AllowHeapAllocation allow_allocation;
|
| + return CallJsBuiltin(isolate, "ArraySlice", args);
|
| + }
|
| + len = Smi::cast(len_obj)->value();
|
| + if (len > object->elements()->length()) {
|
| + AllowHeapAllocation allow_allocation;
|
| return CallJsBuiltin(isolate, "ArraySlice", args);
|
| }
|
| - relative_start = std::isnan(start) ? 0 : static_cast<int>(start);
|
| - } else if (!arg1->IsUndefined()) {
|
| - return CallJsBuiltin(isolate, "ArraySlice", args);
|
| }
|
| - if (n_arguments > 1) {
|
| - Handle<Object> arg2 = args.at<Object>(2);
|
| - if (arg2->IsSmi()) {
|
| - relative_end = Handle<Smi>::cast(arg2)->value();
|
| - } else if (arg2->IsHeapNumber()) {
|
| - double end = Handle<HeapNumber>::cast(arg2)->value();
|
| - if (end < kMinInt || end > kMaxInt) {
|
| +
|
| + ASSERT(len >= 0);
|
| + int n_arguments = args.length() - 1;
|
| +
|
| + // Note carefully choosen defaults---if argument is missing,
|
| + // it's undefined which gets converted to 0 for relative_start
|
| + // and to len for relative_end.
|
| + relative_start = 0;
|
| + relative_end = len;
|
| + if (n_arguments > 0) {
|
| + Object* arg1 = args[1];
|
| + if (arg1->IsSmi()) {
|
| + relative_start = Smi::cast(arg1)->value();
|
| + } else if (arg1->IsHeapNumber()) {
|
| + double start = HeapNumber::cast(arg1)->value();
|
| + if (start < kMinInt || start > kMaxInt) {
|
| + AllowHeapAllocation allow_allocation;
|
| return CallJsBuiltin(isolate, "ArraySlice", args);
|
| }
|
| - relative_end = std::isnan(end) ? 0 : static_cast<int>(end);
|
| - } else if (!arg2->IsUndefined()) {
|
| + relative_start = std::isnan(start) ? 0 : static_cast<int>(start);
|
| + } else if (!arg1->IsUndefined()) {
|
| + AllowHeapAllocation allow_allocation;
|
| return CallJsBuiltin(isolate, "ArraySlice", args);
|
| }
|
| + if (n_arguments > 1) {
|
| + Object* arg2 = args[2];
|
| + if (arg2->IsSmi()) {
|
| + relative_end = Smi::cast(arg2)->value();
|
| + } else if (arg2->IsHeapNumber()) {
|
| + double end = HeapNumber::cast(arg2)->value();
|
| + if (end < kMinInt || end > kMaxInt) {
|
| + AllowHeapAllocation allow_allocation;
|
| + return CallJsBuiltin(isolate, "ArraySlice", args);
|
| + }
|
| + relative_end = std::isnan(end) ? 0 : static_cast<int>(end);
|
| + } else if (!arg2->IsUndefined()) {
|
| + AllowHeapAllocation allow_allocation;
|
| + return CallJsBuiltin(isolate, "ArraySlice", args);
|
| + }
|
| + }
|
| }
|
| }
|
|
|
| @@ -740,13 +735,16 @@ BUILTIN(ArraySlice) {
|
| // Calculate the length of result array.
|
| int result_len = Max(final - k, 0);
|
|
|
| + Handle<JSObject> object = Handle<JSObject>::cast(receiver);
|
| + Handle<FixedArrayBase> elms(object->elements(), isolate);
|
| +
|
| ElementsKind kind = object->GetElementsKind();
|
| if (IsHoleyElementsKind(kind)) {
|
| + DisallowHeapAllocation no_gc;
|
| bool packed = true;
|
| ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
|
| for (int i = k; i < final; i++) {
|
| - if (!ElementsAccessorHasElementWrapper(
|
| - accessor, object, object, i, elms)) {
|
| + if (!accessor->HasElement(*object, *object, i, *elms)) {
|
| packed = false;
|
| break;
|
| }
|
| @@ -754,6 +752,7 @@ BUILTIN(ArraySlice) {
|
| if (packed) {
|
| kind = GetPackedElementsKind(kind);
|
| } else if (!receiver->IsJSArray()) {
|
| + AllowHeapAllocation allow_allocation;
|
| return CallJsBuiltin(isolate, "ArraySlice", args);
|
| }
|
| }
|
| @@ -765,8 +764,8 @@ BUILTIN(ArraySlice) {
|
| if (result_len == 0) return *result_array;
|
|
|
| ElementsAccessor* accessor = object->GetElementsAccessor();
|
| - accessor->CopyElements(Handle<JSObject>::null(), k, kind,
|
| - handle(result_array->elements()), 0, result_len, elms);
|
| + accessor->CopyElements(
|
| + elms, k, kind, handle(result_array->elements(), isolate), 0, result_len);
|
| return *result_array;
|
| }
|
|
|
| @@ -791,16 +790,19 @@ BUILTIN(ArraySplice) {
|
|
|
| int relative_start = 0;
|
| if (n_arguments > 0) {
|
| - Handle<Object> arg1 = args.at<Object>(1);
|
| + DisallowHeapAllocation no_gc;
|
| + Object* arg1 = args[1];
|
| if (arg1->IsSmi()) {
|
| - relative_start = Handle<Smi>::cast(arg1)->value();
|
| + relative_start = Smi::cast(arg1)->value();
|
| } else if (arg1->IsHeapNumber()) {
|
| - double start = Handle<HeapNumber>::cast(arg1)->value();
|
| + double start = HeapNumber::cast(arg1)->value();
|
| if (start < kMinInt || start > kMaxInt) {
|
| + AllowHeapAllocation allow_allocation;
|
| return CallJsBuiltin(isolate, "ArraySplice", args);
|
| }
|
| relative_start = std::isnan(start) ? 0 : static_cast<int>(start);
|
| } else if (!arg1->IsUndefined()) {
|
| + AllowHeapAllocation allow_allocation;
|
| return CallJsBuiltin(isolate, "ArraySplice", args);
|
| }
|
| }
|
| @@ -819,10 +821,12 @@ BUILTIN(ArraySplice) {
|
| } else {
|
| int value = 0; // ToInteger(undefined) == 0
|
| if (n_arguments > 1) {
|
| + DisallowHeapAllocation no_gc;
|
| Object* arg2 = args[2];
|
| if (arg2->IsSmi()) {
|
| value = Smi::cast(arg2)->value();
|
| } else {
|
| + AllowHeapAllocation allow_allocation;
|
| return CallJsBuiltin(isolate, "ArraySplice", args);
|
| }
|
| }
|
| @@ -856,8 +860,8 @@ BUILTIN(ArraySplice) {
|
| DisallowHeapAllocation no_gc;
|
| ElementsAccessor* accessor = array->GetElementsAccessor();
|
| accessor->CopyElements(
|
| - Handle<JSObject>::null(), actual_start, elements_kind,
|
| - handle(result_array->elements()), 0, actual_delete_count, elms_obj);
|
| + elms_obj, actual_start, elements_kind,
|
| + handle(result_array->elements(), isolate), 0, actual_delete_count);
|
| }
|
|
|
| bool elms_changed = false;
|
| @@ -881,7 +885,7 @@ BUILTIN(ArraySplice) {
|
|
|
| if (heap->CanMoveObjectStart(*elms_obj)) {
|
| // On the fast path we move the start of the object in memory.
|
| - elms_obj = handle(LeftTrimFixedArray(heap, *elms_obj, delta));
|
| + elms_obj = handle(LeftTrimFixedArray(heap, *elms_obj, delta), isolate);
|
| } else {
|
| // This is the slow path. We are going to move the elements to the left
|
| // by copying them. For trimmed values we store the hole.
|
| @@ -935,12 +939,12 @@ BUILTIN(ArraySplice) {
|
| if (actual_start > 0) {
|
| // Copy the part before actual_start as is.
|
| accessor->CopyElements(
|
| - Handle<JSObject>::null(), 0, kind, new_elms, 0, actual_start, elms);
|
| + elms, 0, kind, new_elms, 0, actual_start);
|
| }
|
| accessor->CopyElements(
|
| - Handle<JSObject>::null(), actual_start + actual_delete_count, kind,
|
| + elms, actual_start + actual_delete_count, kind,
|
| new_elms, actual_start + item_count,
|
| - ElementsAccessor::kCopyToEndAndInitializeToHole, elms);
|
| + ElementsAccessor::kCopyToEndAndInitializeToHole);
|
|
|
| elms_obj = new_elms;
|
| elms_changed = true;
|
| @@ -984,9 +988,9 @@ BUILTIN(ArraySplice) {
|
| BUILTIN(ArrayConcat) {
|
| HandleScope scope(isolate);
|
| Heap* heap = isolate->heap();
|
| - Handle<Context> native_context(isolate->context()->native_context());
|
| + Handle<Context> native_context(isolate->context()->native_context(), isolate);
|
| Handle<JSObject> array_proto(
|
| - JSObject::cast(native_context->array_function()->prototype()));
|
| + JSObject::cast(native_context->array_function()->prototype()), isolate);
|
| if (!ArrayPrototypeHasNoElements(heap, *native_context, *array_proto)) {
|
| return CallJsBuiltin(isolate, "ArrayConcat", args);
|
| }
|
| @@ -999,13 +1003,15 @@ BUILTIN(ArrayConcat) {
|
| bool has_double = false;
|
| bool is_holey = false;
|
| for (int i = 0; i < n_arguments; i++) {
|
| - Handle<Object> arg = args.at<Object>(i);
|
| + DisallowHeapAllocation no_gc;
|
| + Object* arg = args[i];
|
| if (!arg->IsJSArray() ||
|
| - !Handle<JSArray>::cast(arg)->HasFastElements() ||
|
| - Handle<JSArray>::cast(arg)->GetPrototype() != *array_proto) {
|
| + !JSArray::cast(arg)->HasFastElements() ||
|
| + JSArray::cast(arg)->GetPrototype() != *array_proto) {
|
| + AllowHeapAllocation allow_allocation;
|
| return CallJsBuiltin(isolate, "ArrayConcat", args);
|
| }
|
| - int len = Smi::cast(Handle<JSArray>::cast(arg)->length())->value();
|
| + int len = Smi::cast(JSArray::cast(arg)->length())->value();
|
|
|
| // We shouldn't overflow when adding another len.
|
| const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2);
|
| @@ -1015,10 +1021,11 @@ BUILTIN(ArrayConcat) {
|
| ASSERT(result_len >= 0);
|
|
|
| if (result_len > FixedDoubleArray::kMaxLength) {
|
| + AllowHeapAllocation allow_allocation;
|
| return CallJsBuiltin(isolate, "ArrayConcat", args);
|
| }
|
|
|
| - ElementsKind arg_kind = Handle<JSArray>::cast(arg)->map()->elements_kind();
|
| + ElementsKind arg_kind = JSArray::cast(arg)->map()->elements_kind();
|
| has_double = has_double || IsFastDoubleElementsKind(arg_kind);
|
| is_holey = is_holey || IsFastHoleyElementsKind(arg_kind);
|
| if (IsMoreGeneralElementsKindTransition(elements_kind, arg_kind)) {
|
| @@ -1042,10 +1049,12 @@ BUILTIN(ArrayConcat) {
|
| if (result_len == 0) return *result_array;
|
|
|
| int j = 0;
|
| - Handle<FixedArrayBase> storage(result_array->elements());
|
| + Handle<FixedArrayBase> storage(result_array->elements(), isolate);
|
| ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind);
|
| for (int i = 0; i < n_arguments; i++) {
|
| - Handle<JSArray> array = args.at<JSArray>(i);
|
| + // TODO(ishell): It is crucial to keep |array| as a raw pointer to avoid
|
| + // performance degradation. Revisit this later.
|
| + JSArray* array = JSArray::cast(args[i]);
|
| int len = Smi::cast(array->length())->value();
|
| ElementsKind from_kind = array->GetElementsKind();
|
| if (len > 0) {
|
|
|