Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1524)

Side by Side Diff: src/builtins.cc

Issue 212573007: ElementsAccessor::CopyElements() and its callers handlified. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | src/elements.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 633 matching lines...) Expand 10 before | Expand all | Expand 10 after
644 elms->set(i, args[i + 1], mode); 644 elms->set(i, args[i + 1], mode);
645 } 645 }
646 646
647 // Set the length. 647 // Set the length.
648 array->set_length(Smi::FromInt(new_length)); 648 array->set_length(Smi::FromInt(new_length));
649 return Smi::FromInt(new_length); 649 return Smi::FromInt(new_length);
650 } 650 }
651 651
652 652
653 BUILTIN(ArraySlice) { 653 BUILTIN(ArraySlice) {
654 HandleScope scope(isolate);
654 Heap* heap = isolate->heap(); 655 Heap* heap = isolate->heap();
655 Object* receiver = *args.receiver(); 656 Handle<Object> receiver = args.receiver();
656 FixedArrayBase* elms; 657 Handle<FixedArrayBase> elms;
657 int len = -1; 658 int len = -1;
658 if (receiver->IsJSArray()) { 659 if (receiver->IsJSArray()) {
659 JSArray* array = JSArray::cast(receiver); 660 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
660 if (!IsJSArrayFastElementMovingAllowed(heap, array)) { 661 if (!IsJSArrayFastElementMovingAllowed(heap, *array)) {
661 return CallJsBuiltin(isolate, "ArraySlice", args); 662 return CallJsBuiltin(isolate, "ArraySlice", args);
662 } 663 }
663 664
664 if (array->HasFastElements()) { 665 if (array->HasFastElements()) {
665 elms = array->elements(); 666 elms = handle(array->elements());
666 } else { 667 } else {
667 return CallJsBuiltin(isolate, "ArraySlice", args); 668 return CallJsBuiltin(isolate, "ArraySlice", args);
668 } 669 }
669 670
670 len = Smi::cast(array->length())->value(); 671 len = Smi::cast(array->length())->value();
671 } else { 672 } else {
672 // Array.slice(arguments, ...) is quite a common idiom (notably more 673 // Array.slice(arguments, ...) is quite a common idiom (notably more
673 // than 50% of invocations in Web apps). Treat it in C++ as well. 674 // than 50% of invocations in Web apps). Treat it in C++ as well.
674 Map* arguments_map = isolate->context()->native_context()-> 675 Handle<Map> arguments_map(isolate->context()->native_context()->
675 sloppy_arguments_boilerplate()->map(); 676 sloppy_arguments_boilerplate()->map());
676 677
677 bool is_arguments_object_with_fast_elements = 678 bool is_arguments_object_with_fast_elements =
678 receiver->IsJSObject() && 679 receiver->IsJSObject() &&
679 JSObject::cast(receiver)->map() == arguments_map; 680 Handle<JSObject>::cast(receiver)->map() == *arguments_map;
680 if (!is_arguments_object_with_fast_elements) { 681 if (!is_arguments_object_with_fast_elements) {
681 return CallJsBuiltin(isolate, "ArraySlice", args); 682 return CallJsBuiltin(isolate, "ArraySlice", args);
682 } 683 }
683 JSObject* object = JSObject::cast(receiver); 684 Handle<JSObject> object = Handle<JSObject>::cast(receiver);
684 685
685 if (object->HasFastElements()) { 686 if (object->HasFastElements()) {
686 elms = object->elements(); 687 elms = handle(object->elements());
687 } else { 688 } else {
688 return CallJsBuiltin(isolate, "ArraySlice", args); 689 return CallJsBuiltin(isolate, "ArraySlice", args);
689 } 690 }
690 Object* len_obj = object->InObjectPropertyAt(Heap::kArgumentsLengthIndex); 691 Handle<Object> len_obj(
692 object->InObjectPropertyAt(Heap::kArgumentsLengthIndex), isolate);
691 if (!len_obj->IsSmi()) { 693 if (!len_obj->IsSmi()) {
692 return CallJsBuiltin(isolate, "ArraySlice", args); 694 return CallJsBuiltin(isolate, "ArraySlice", args);
693 } 695 }
694 len = Smi::cast(len_obj)->value(); 696 len = Handle<Smi>::cast(len_obj)->value();
695 if (len > elms->length()) { 697 if (len > elms->length()) {
696 return CallJsBuiltin(isolate, "ArraySlice", args); 698 return CallJsBuiltin(isolate, "ArraySlice", args);
697 } 699 }
698 } 700 }
699 701
700 JSObject* object = JSObject::cast(receiver); 702 Handle<JSObject> object = Handle<JSObject>::cast(receiver);
701 703
702 ASSERT(len >= 0); 704 ASSERT(len >= 0);
703 int n_arguments = args.length() - 1; 705 int n_arguments = args.length() - 1;
704 706
705 // Note carefully choosen defaults---if argument is missing, 707 // Note carefully choosen defaults---if argument is missing,
706 // it's undefined which gets converted to 0 for relative_start 708 // it's undefined which gets converted to 0 for relative_start
707 // and to len for relative_end. 709 // and to len for relative_end.
708 int relative_start = 0; 710 int relative_start = 0;
709 int relative_end = len; 711 int relative_end = len;
710 if (n_arguments > 0) { 712 if (n_arguments > 0) {
711 Object* arg1 = args[1]; 713 Handle<Object> arg1 = args.at<Object>(1);
712 if (arg1->IsSmi()) { 714 if (arg1->IsSmi()) {
713 relative_start = Smi::cast(arg1)->value(); 715 relative_start = Handle<Smi>::cast(arg1)->value();
714 } else if (arg1->IsHeapNumber()) { 716 } else if (arg1->IsHeapNumber()) {
715 double start = HeapNumber::cast(arg1)->value(); 717 double start = Handle<HeapNumber>::cast(arg1)->value();
716 if (start < kMinInt || start > kMaxInt) { 718 if (start < kMinInt || start > kMaxInt) {
717 return CallJsBuiltin(isolate, "ArraySlice", args); 719 return CallJsBuiltin(isolate, "ArraySlice", args);
718 } 720 }
719 relative_start = std::isnan(start) ? 0 : static_cast<int>(start); 721 relative_start = std::isnan(start) ? 0 : static_cast<int>(start);
720 } else if (!arg1->IsUndefined()) { 722 } else if (!arg1->IsUndefined()) {
721 return CallJsBuiltin(isolate, "ArraySlice", args); 723 return CallJsBuiltin(isolate, "ArraySlice", args);
722 } 724 }
723 if (n_arguments > 1) { 725 if (n_arguments > 1) {
724 Object* arg2 = args[2]; 726 Handle<Object> arg2 = args.at<Object>(2);
725 if (arg2->IsSmi()) { 727 if (arg2->IsSmi()) {
726 relative_end = Smi::cast(arg2)->value(); 728 relative_end = Handle<Smi>::cast(arg2)->value();
727 } else if (arg2->IsHeapNumber()) { 729 } else if (arg2->IsHeapNumber()) {
728 double end = HeapNumber::cast(arg2)->value(); 730 double end = Handle<HeapNumber>::cast(arg2)->value();
729 if (end < kMinInt || end > kMaxInt) { 731 if (end < kMinInt || end > kMaxInt) {
730 return CallJsBuiltin(isolate, "ArraySlice", args); 732 return CallJsBuiltin(isolate, "ArraySlice", args);
731 } 733 }
732 relative_end = std::isnan(end) ? 0 : static_cast<int>(end); 734 relative_end = std::isnan(end) ? 0 : static_cast<int>(end);
733 } else if (!arg2->IsUndefined()) { 735 } else if (!arg2->IsUndefined()) {
734 return CallJsBuiltin(isolate, "ArraySlice", args); 736 return CallJsBuiltin(isolate, "ArraySlice", args);
735 } 737 }
736 } 738 }
737 } 739 }
738 740
739 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 6. 741 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 6.
740 int k = (relative_start < 0) ? Max(len + relative_start, 0) 742 int k = (relative_start < 0) ? Max(len + relative_start, 0)
741 : Min(relative_start, len); 743 : Min(relative_start, len);
742 744
743 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8. 745 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8.
744 int final = (relative_end < 0) ? Max(len + relative_end, 0) 746 int final = (relative_end < 0) ? Max(len + relative_end, 0)
745 : Min(relative_end, len); 747 : Min(relative_end, len);
746 748
747 // Calculate the length of result array. 749 // Calculate the length of result array.
748 int result_len = Max(final - k, 0); 750 int result_len = Max(final - k, 0);
749 751
750 ElementsKind kind = object->GetElementsKind(); 752 ElementsKind kind = object->GetElementsKind();
751 if (IsHoleyElementsKind(kind)) { 753 if (IsHoleyElementsKind(kind)) {
752 bool packed = true; 754 bool packed = true;
753 ElementsAccessor* accessor = ElementsAccessor::ForKind(kind); 755 ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
754 for (int i = k; i < final; i++) { 756 for (int i = k; i < final; i++) {
755 if (!accessor->HasElement(object, object, i, elms)) { 757 if (!ElementsAccessorHasElementWrapper(
758 accessor, object, object, i, elms)) {
756 packed = false; 759 packed = false;
757 break; 760 break;
758 } 761 }
759 } 762 }
760 if (packed) { 763 if (packed) {
761 kind = GetPackedElementsKind(kind); 764 kind = GetPackedElementsKind(kind);
762 } else if (!receiver->IsJSArray()) { 765 } else if (!receiver->IsJSArray()) {
763 return CallJsBuiltin(isolate, "ArraySlice", args); 766 return CallJsBuiltin(isolate, "ArraySlice", args);
764 } 767 }
765 } 768 }
766 769
767 JSArray* result_array; 770 Handle<JSArray> result_array =
768 MaybeObject* maybe_array = heap->AllocateJSArrayAndStorage(kind, 771 isolate->factory()->NewJSArray(kind, result_len, result_len);
769 result_len,
770 result_len);
771 772
772 DisallowHeapAllocation no_gc; 773 DisallowHeapAllocation no_gc;
773 if (result_len == 0) return maybe_array; 774 if (result_len == 0) return *result_array;
774 if (!maybe_array->To(&result_array)) return maybe_array;
775 775
776 ElementsAccessor* accessor = object->GetElementsAccessor(); 776 ElementsAccessor* accessor = object->GetElementsAccessor();
777 MaybeObject* maybe_failure = accessor->CopyElements( 777 accessor->CopyElements(Handle<JSObject>::null(), k, kind,
778 NULL, k, kind, result_array->elements(), 0, result_len, elms); 778 handle(result_array->elements()), 0, result_len, elms);
Yang 2014/03/27 15:39:22 CopyElements cannot throw, correct?
Igor Sheludko 2014/03/27 16:00:10 Yes, it can't.
779 ASSERT(!maybe_failure->IsFailure()); 779 return *result_array;
780 USE(maybe_failure);
781
782 return result_array;
783 } 780 }
784 781
785 782
786 BUILTIN(ArraySplice) { 783 BUILTIN(ArraySplice) {
787 HandleScope scope(isolate); 784 HandleScope scope(isolate);
788 Heap* heap = isolate->heap(); 785 Heap* heap = isolate->heap();
789 Handle<Object> receiver = args.receiver(); 786 Handle<Object> receiver = args.receiver();
790 Handle<FixedArrayBase> elms_obj = 787 Handle<FixedArrayBase> elms_obj =
791 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 3); 788 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 3);
792 if (elms_obj.is_null() || 789 if (elms_obj.is_null() ||
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
987 array->set_elements(*elms_obj); 984 array->set_elements(*elms_obj);
988 } 985 }
989 // Set the length. 986 // Set the length.
990 array->set_length(Smi::FromInt(new_length)); 987 array->set_length(Smi::FromInt(new_length));
991 988
992 return *result_array; 989 return *result_array;
993 } 990 }
994 991
995 992
996 BUILTIN(ArrayConcat) { 993 BUILTIN(ArrayConcat) {
994 HandleScope scope(isolate);
997 Heap* heap = isolate->heap(); 995 Heap* heap = isolate->heap();
998 Context* native_context = isolate->context()->native_context(); 996 Handle<Context> native_context(isolate->context()->native_context());
999 JSObject* array_proto = 997 Handle<JSObject> array_proto(
1000 JSObject::cast(native_context->array_function()->prototype()); 998 JSObject::cast(native_context->array_function()->prototype()));
1001 if (!ArrayPrototypeHasNoElements(heap, native_context, array_proto)) { 999 if (!ArrayPrototypeHasNoElements(heap, *native_context, *array_proto)) {
1002 return CallJsBuiltin(isolate, "ArrayConcat", args); 1000 return CallJsBuiltin(isolate, "ArrayConcat", args);
1003 } 1001 }
1004 1002
1005 // Iterate through all the arguments performing checks 1003 // Iterate through all the arguments performing checks
1006 // and calculating total length. 1004 // and calculating total length.
1007 int n_arguments = args.length(); 1005 int n_arguments = args.length();
1008 int result_len = 0; 1006 int result_len = 0;
1009 ElementsKind elements_kind = GetInitialFastElementsKind(); 1007 ElementsKind elements_kind = GetInitialFastElementsKind();
1010 bool has_double = false; 1008 bool has_double = false;
1011 bool is_holey = false; 1009 bool is_holey = false;
1012 for (int i = 0; i < n_arguments; i++) { 1010 for (int i = 0; i < n_arguments; i++) {
1013 Object* arg = args[i]; 1011 Handle<Object> arg = args.at<Object>(i);
1014 if (!arg->IsJSArray() || 1012 if (!arg->IsJSArray() ||
1015 !JSArray::cast(arg)->HasFastElements() || 1013 !Handle<JSArray>::cast(arg)->HasFastElements() ||
1016 JSArray::cast(arg)->GetPrototype() != array_proto) { 1014 Handle<JSArray>::cast(arg)->GetPrototype() != *array_proto) {
1017 return CallJsBuiltin(isolate, "ArrayConcat", args); 1015 return CallJsBuiltin(isolate, "ArrayConcat", args);
1018 } 1016 }
1019 int len = Smi::cast(JSArray::cast(arg)->length())->value(); 1017 int len = Smi::cast(Handle<JSArray>::cast(arg)->length())->value();
1020 1018
1021 // We shouldn't overflow when adding another len. 1019 // We shouldn't overflow when adding another len.
1022 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2); 1020 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2);
1023 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt); 1021 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt);
1024 USE(kHalfOfMaxInt); 1022 USE(kHalfOfMaxInt);
1025 result_len += len; 1023 result_len += len;
1026 ASSERT(result_len >= 0); 1024 ASSERT(result_len >= 0);
1027 1025
1028 if (result_len > FixedDoubleArray::kMaxLength) { 1026 if (result_len > FixedDoubleArray::kMaxLength) {
1029 return CallJsBuiltin(isolate, "ArrayConcat", args); 1027 return CallJsBuiltin(isolate, "ArrayConcat", args);
1030 } 1028 }
1031 1029
1032 ElementsKind arg_kind = JSArray::cast(arg)->map()->elements_kind(); 1030 ElementsKind arg_kind = Handle<JSArray>::cast(arg)->map()->elements_kind();
1033 has_double = has_double || IsFastDoubleElementsKind(arg_kind); 1031 has_double = has_double || IsFastDoubleElementsKind(arg_kind);
1034 is_holey = is_holey || IsFastHoleyElementsKind(arg_kind); 1032 is_holey = is_holey || IsFastHoleyElementsKind(arg_kind);
1035 if (IsMoreGeneralElementsKindTransition(elements_kind, arg_kind)) { 1033 if (IsMoreGeneralElementsKindTransition(elements_kind, arg_kind)) {
1036 elements_kind = arg_kind; 1034 elements_kind = arg_kind;
1037 } 1035 }
1038 } 1036 }
1039 1037
1040 if (is_holey) elements_kind = GetHoleyElementsKind(elements_kind); 1038 if (is_holey) elements_kind = GetHoleyElementsKind(elements_kind);
1041 1039
1042 // If a double array is concatted into a fast elements array, the fast 1040 // If a double array is concatted into a fast elements array, the fast
1043 // elements array needs to be initialized to contain proper holes, since 1041 // elements array needs to be initialized to contain proper holes, since
1044 // boxing doubles may cause incremental marking. 1042 // boxing doubles may cause incremental marking.
1045 ArrayStorageAllocationMode mode = 1043 ArrayStorageAllocationMode mode =
1046 has_double && IsFastObjectElementsKind(elements_kind) 1044 has_double && IsFastObjectElementsKind(elements_kind)
1047 ? INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE : DONT_INITIALIZE_ARRAY_ELEMENTS; 1045 ? INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE : DONT_INITIALIZE_ARRAY_ELEMENTS;
1048 JSArray* result_array; 1046 Handle<JSArray> result_array =
1049 // Allocate result. 1047 isolate->factory()->NewJSArray(elements_kind,
1050 MaybeObject* maybe_array = 1048 result_len,
1051 heap->AllocateJSArrayAndStorage(elements_kind, 1049 result_len,
1052 result_len, 1050 mode);
1053 result_len, 1051 if (result_len == 0) return *result_array;
1054 mode);
1055 if (!maybe_array->To(&result_array)) return maybe_array;
1056 if (result_len == 0) return result_array;
1057 1052
1058 int j = 0; 1053 int j = 0;
1059 FixedArrayBase* storage = result_array->elements(); 1054 Handle<FixedArrayBase> storage(result_array->elements());
1060 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); 1055 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind);
1061 for (int i = 0; i < n_arguments; i++) { 1056 for (int i = 0; i < n_arguments; i++) {
1062 JSArray* array = JSArray::cast(args[i]); 1057 Handle<JSArray> array = args.at<JSArray>(i);
1063 int len = Smi::cast(array->length())->value(); 1058 int len = Smi::cast(array->length())->value();
1064 ElementsKind from_kind = array->GetElementsKind(); 1059 ElementsKind from_kind = array->GetElementsKind();
1065 if (len > 0) { 1060 if (len > 0) {
1066 MaybeObject* maybe_failure = 1061 accessor->CopyElements(array, 0, from_kind, storage, j, len);
1067 accessor->CopyElements(array, 0, from_kind, storage, j, len);
1068 if (maybe_failure->IsFailure()) return maybe_failure;
1069 j += len; 1062 j += len;
1070 } 1063 }
1071 } 1064 }
1072 1065
1073 ASSERT(j == result_len); 1066 ASSERT(j == result_len);
1074 1067
1075 return result_array; 1068 return *result_array;
1076 } 1069 }
1077 1070
1078 1071
1079 // ----------------------------------------------------------------------------- 1072 // -----------------------------------------------------------------------------
1080 // Strict mode poison pills 1073 // Strict mode poison pills
1081 1074
1082 1075
1083 BUILTIN(StrictModePoisonPill) { 1076 BUILTIN(StrictModePoisonPill) {
1084 HandleScope scope(isolate); 1077 HandleScope scope(isolate);
1085 return isolate->Throw(*isolate->factory()->NewTypeError( 1078 return isolate->Throw(*isolate->factory()->NewTypeError(
(...skipping 649 matching lines...) Expand 10 before | Expand all | Expand 10 after
1735 } 1728 }
1736 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) 1729 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C)
1737 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) 1730 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A)
1738 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) 1731 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H)
1739 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) 1732 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A)
1740 #undef DEFINE_BUILTIN_ACCESSOR_C 1733 #undef DEFINE_BUILTIN_ACCESSOR_C
1741 #undef DEFINE_BUILTIN_ACCESSOR_A 1734 #undef DEFINE_BUILTIN_ACCESSOR_A
1742 1735
1743 1736
1744 } } // namespace v8::internal 1737 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | src/elements.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698