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

Side by Side Diff: src/builtins.cc

Issue 1305763002: Revert of Moving ArraySplice Builtin to ElementsAccessor (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 4 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
« 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 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/api.h" 7 #include "src/api.h"
8 #include "src/api-natives.h" 8 #include "src/api-natives.h"
9 #include "src/arguments.h" 9 #include "src/arguments.h"
10 #include "src/base/once.h" 10 #include "src/base/once.h"
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
169 UNREACHABLE(); 169 UNREACHABLE();
170 return isolate->heap()->undefined_value(); // Make compiler happy. 170 return isolate->heap()->undefined_value(); // Make compiler happy.
171 } 171 }
172 172
173 173
174 BUILTIN(EmptyFunction) { 174 BUILTIN(EmptyFunction) {
175 return isolate->heap()->undefined_value(); 175 return isolate->heap()->undefined_value();
176 } 176 }
177 177
178 178
179 // TODO(cbruni): check if this is a suitable method on Object
180 bool ClampedToInteger(Object* object, int* out) {
181 // This is an extended version of ECMA-262 9.4, but additionally
182 // clamps values to [kMinInt, kMaxInt]
183 if (object->IsSmi()) {
184 *out = Smi::cast(object)->value();
185 return true;
186 } else if (object->IsHeapNumber()) {
187 *out = FastD2IChecked(HeapNumber::cast(object)->value());
188 return true;
189 } else if (object->IsUndefined()) {
190 *out = 0;
191 return true;
192 } else if (object->IsBoolean()) {
193 *out = (Oddball::cast(object)->kind() == Oddball::kTrue) ? 1 : 0;
194 return true;
195 }
196 return false;
197 }
198
199
200 static void MoveDoubleElements(FixedDoubleArray* dst, int dst_index, 179 static void MoveDoubleElements(FixedDoubleArray* dst, int dst_index,
201 FixedDoubleArray* src, int src_index, int len) { 180 FixedDoubleArray* src, int src_index, int len) {
202 if (len == 0) return; 181 if (len == 0) return;
203 MemMove(dst->data_start() + dst_index, src->data_start() + src_index, 182 MemMove(dst->data_start() + dst_index, src->data_start() + src_index,
204 len * kDoubleSize); 183 len * kDoubleSize);
205 } 184 }
206 185
207 186
208 static bool ArrayPrototypeHasNoElements(PrototypeIterator* iter) { 187 static bool ArrayPrototypeHasNoElements(PrototypeIterator* iter) {
209 DisallowHeapAllocation no_gc; 188 DisallowHeapAllocation no_gc;
(...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after
635 614
636 ElementsAccessor* accessor = object->GetElementsAccessor(); 615 ElementsAccessor* accessor = object->GetElementsAccessor();
637 accessor->CopyElements( 616 accessor->CopyElements(
638 elms, k, kind, handle(result_array->elements(), isolate), 0, result_len); 617 elms, k, kind, handle(result_array->elements(), isolate), 0, result_len);
639 return *result_array; 618 return *result_array;
640 } 619 }
641 620
642 621
643 BUILTIN(ArraySplice) { 622 BUILTIN(ArraySplice) {
644 HandleScope scope(isolate); 623 HandleScope scope(isolate);
624 Heap* heap = isolate->heap();
645 Handle<Object> receiver = args.receiver(); 625 Handle<Object> receiver = args.receiver();
646 MaybeHandle<FixedArrayBase> maybe_elms_obj = 626 MaybeHandle<FixedArrayBase> maybe_elms_obj =
647 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 3); 627 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 3);
648 Handle<FixedArrayBase> elms_obj; 628 Handle<FixedArrayBase> elms_obj;
649 if (!maybe_elms_obj.ToHandle(&elms_obj)) { 629 if (!maybe_elms_obj.ToHandle(&elms_obj)) {
650 return CallJsBuiltin(isolate, "$arraySplice", args); 630 return CallJsBuiltin(isolate, "$arraySplice", args);
651 } 631 }
652 Handle<JSArray> array = Handle<JSArray>::cast(receiver); 632 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
653 DCHECK(!array->map()->is_observed()); 633 DCHECK(!array->map()->is_observed());
654 634
655 int argument_count = args.length() - 1; 635 int len = Smi::cast(array->length())->value();
636
637 int n_arguments = args.length() - 1;
638
656 int relative_start = 0; 639 int relative_start = 0;
657 if (argument_count > 0) { 640 if (n_arguments > 0) {
658 DisallowHeapAllocation no_gc; 641 DisallowHeapAllocation no_gc;
659 if (!ClampedToInteger(args[1], &relative_start)) { 642 Object* arg1 = args[1];
643 if (arg1->IsSmi()) {
644 relative_start = Smi::cast(arg1)->value();
645 } else if (arg1->IsHeapNumber()) {
646 double start = HeapNumber::cast(arg1)->value();
647 if (start < kMinInt || start > kMaxInt) {
648 AllowHeapAllocation allow_allocation;
649 return CallJsBuiltin(isolate, "$arraySplice", args);
650 }
651 relative_start = std::isnan(start) ? 0 : static_cast<int>(start);
652 } else if (!arg1->IsUndefined()) {
660 AllowHeapAllocation allow_allocation; 653 AllowHeapAllocation allow_allocation;
661 return CallJsBuiltin(isolate, "$arraySplice", args); 654 return CallJsBuiltin(isolate, "$arraySplice", args);
662 } 655 }
663 } 656 }
664 int len = Smi::cast(array->length())->value();
665 // clip relative start to [0, len]
666 int actual_start = (relative_start < 0) ? Max(len + relative_start, 0) 657 int actual_start = (relative_start < 0) ? Max(len + relative_start, 0)
667 : Min(relative_start, len); 658 : Min(relative_start, len);
668 659
660 // SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is
661 // given as a request to delete all the elements from the start.
662 // And it differs from the case of undefined delete count.
663 // This does not follow ECMA-262, but we do the same for
664 // compatibility.
669 int actual_delete_count; 665 int actual_delete_count;
670 if (argument_count == 1) { 666 if (n_arguments == 1) {
671 // SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is
672 // given as a request to delete all the elements from the start.
673 // And it differs from the case of undefined delete count.
674 // This does not follow ECMA-262, but we do the same for compatibility.
675 DCHECK(len - actual_start >= 0); 667 DCHECK(len - actual_start >= 0);
676 actual_delete_count = len - actual_start; 668 actual_delete_count = len - actual_start;
677 } else { 669 } else {
678 int delete_count = 0; 670 int value = 0; // ToInteger(undefined) == 0
679 DisallowHeapAllocation no_gc; 671 if (n_arguments > 1) {
680 if (argument_count > 1) { 672 DisallowHeapAllocation no_gc;
681 if (!ClampedToInteger(args[2], &delete_count)) { 673 Object* arg2 = args[2];
674 if (arg2->IsSmi()) {
675 value = Smi::cast(arg2)->value();
676 } else {
682 AllowHeapAllocation allow_allocation; 677 AllowHeapAllocation allow_allocation;
683 return CallJsBuiltin(isolate, "$arraySplice", args); 678 return CallJsBuiltin(isolate, "$arraySplice", args);
684 } 679 }
685 } 680 }
686 actual_delete_count = Min(Max(delete_count, 0), len - actual_start); 681 actual_delete_count = Min(Max(value, 0), len - actual_start);
687 } 682 }
688 683
689 int add_count = (argument_count > 1) ? (argument_count - 2) : 0; 684 ElementsKind elements_kind = array->GetElementsKind();
690 int new_length = len - actual_delete_count + add_count; 685
686 int item_count = (n_arguments > 1) ? (n_arguments - 2) : 0;
687 int new_length = len - actual_delete_count + item_count;
688
689 // For double mode we do not support changing the length.
690 if (new_length > len && IsFastDoubleElementsKind(elements_kind)) {
691 return CallJsBuiltin(isolate, "$arraySplice", args);
692 }
691 693
692 if (new_length != len && JSArray::HasReadOnlyLength(array)) { 694 if (new_length != len && JSArray::HasReadOnlyLength(array)) {
693 AllowHeapAllocation allow_allocation; 695 AllowHeapAllocation allow_allocation;
694 return CallJsBuiltin(isolate, "$arraySplice", args); 696 return CallJsBuiltin(isolate, "$arraySplice", args);
695 } 697 }
696 ElementsAccessor* accessor = array->GetElementsAccessor(); 698
697 Handle<JSArray> result = accessor->Splice( 699 if (new_length == 0) {
698 array, elms_obj, actual_start, actual_delete_count, args, add_count); 700 Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(
699 return *result; 701 elms_obj, elements_kind, actual_delete_count);
702 array->set_elements(heap->empty_fixed_array());
703 array->set_length(Smi::FromInt(0));
704 return *result;
705 }
706
707 Handle<JSArray> result_array =
708 isolate->factory()->NewJSArray(elements_kind,
709 actual_delete_count,
710 actual_delete_count);
711
712 if (actual_delete_count > 0) {
713 DisallowHeapAllocation no_gc;
714 ElementsAccessor* accessor = array->GetElementsAccessor();
715 accessor->CopyElements(
716 elms_obj, actual_start, elements_kind,
717 handle(result_array->elements(), isolate), 0, actual_delete_count);
718 }
719
720 bool elms_changed = false;
721 if (item_count < actual_delete_count) {
722 // Shrink the array.
723 const bool trim_array = !heap->lo_space()->Contains(*elms_obj) &&
724 ((actual_start + item_count) <
725 (len - actual_delete_count - actual_start));
726 if (trim_array) {
727 const int delta = actual_delete_count - item_count;
728
729 if (elms_obj->IsFixedDoubleArray()) {
730 Handle<FixedDoubleArray> elms =
731 Handle<FixedDoubleArray>::cast(elms_obj);
732 MoveDoubleElements(*elms, delta, *elms, 0, actual_start);
733 } else {
734 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
735 DisallowHeapAllocation no_gc;
736 heap->MoveElements(*elms, delta, 0, actual_start);
737 }
738
739 if (heap->CanMoveObjectStart(*elms_obj)) {
740 // On the fast path we move the start of the object in memory.
741 elms_obj = handle(heap->LeftTrimFixedArray(*elms_obj, delta));
742 } else {
743 // This is the slow path. We are going to move the elements to the left
744 // by copying them. For trimmed values we store the hole.
745 if (elms_obj->IsFixedDoubleArray()) {
746 Handle<FixedDoubleArray> elms =
747 Handle<FixedDoubleArray>::cast(elms_obj);
748 MoveDoubleElements(*elms, 0, *elms, delta, len - delta);
749 elms->FillWithHoles(len - delta, len);
750 } else {
751 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
752 DisallowHeapAllocation no_gc;
753 heap->MoveElements(*elms, 0, delta, len - delta);
754 elms->FillWithHoles(len - delta, len);
755 }
756 }
757 elms_changed = true;
758 } else {
759 if (elms_obj->IsFixedDoubleArray()) {
760 Handle<FixedDoubleArray> elms =
761 Handle<FixedDoubleArray>::cast(elms_obj);
762 MoveDoubleElements(*elms, actual_start + item_count,
763 *elms, actual_start + actual_delete_count,
764 (len - actual_delete_count - actual_start));
765 elms->FillWithHoles(new_length, len);
766 } else {
767 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
768 DisallowHeapAllocation no_gc;
769 heap->MoveElements(*elms, actual_start + item_count,
770 actual_start + actual_delete_count,
771 (len - actual_delete_count - actual_start));
772 elms->FillWithHoles(new_length, len);
773 }
774 }
775 } else if (item_count > actual_delete_count) {
776 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
777 // Currently fixed arrays cannot grow too big, so
778 // we should never hit this case.
779 DCHECK((item_count - actual_delete_count) <= (Smi::kMaxValue - len));
780
781 // Check if array need to grow.
782 if (new_length > elms->length()) {
783 // New backing storage is needed.
784 int capacity = new_length + (new_length >> 1) + 16;
785 Handle<FixedArray> new_elms =
786 isolate->factory()->NewUninitializedFixedArray(capacity);
787
788 DisallowHeapAllocation no_gc;
789
790 ElementsKind kind = array->GetElementsKind();
791 ElementsAccessor* accessor = array->GetElementsAccessor();
792 if (actual_start > 0) {
793 // Copy the part before actual_start as is.
794 accessor->CopyElements(
795 elms, 0, kind, new_elms, 0, actual_start);
796 }
797 accessor->CopyElements(
798 elms, actual_start + actual_delete_count, kind,
799 new_elms, actual_start + item_count,
800 ElementsAccessor::kCopyToEndAndInitializeToHole);
801
802 elms_obj = new_elms;
803 elms_changed = true;
804 } else {
805 DisallowHeapAllocation no_gc;
806 heap->MoveElements(*elms, actual_start + item_count,
807 actual_start + actual_delete_count,
808 (len - actual_delete_count - actual_start));
809 }
810 }
811
812 if (IsFastDoubleElementsKind(elements_kind)) {
813 Handle<FixedDoubleArray> elms = Handle<FixedDoubleArray>::cast(elms_obj);
814 for (int k = actual_start; k < actual_start + item_count; k++) {
815 Object* arg = args[3 + k - actual_start];
816 if (arg->IsSmi()) {
817 elms->set(k, Smi::cast(arg)->value());
818 } else {
819 elms->set(k, HeapNumber::cast(arg)->value());
820 }
821 }
822 } else {
823 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
824 DisallowHeapAllocation no_gc;
825 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
826 for (int k = actual_start; k < actual_start + item_count; k++) {
827 elms->set(k, args[3 + k - actual_start], mode);
828 }
829 }
830
831 if (elms_changed) {
832 array->set_elements(*elms_obj);
833 }
834 // Set the length.
835 array->set_length(Smi::FromInt(new_length));
836
837 return *result_array;
700 } 838 }
701 839
702 840
703 BUILTIN(ArrayConcat) { 841 BUILTIN(ArrayConcat) {
704 HandleScope scope(isolate); 842 HandleScope scope(isolate);
705 843
706 int n_arguments = args.length(); 844 int n_arguments = args.length();
707 int result_len = 0; 845 int result_len = 0;
708 ElementsKind elements_kind = GetInitialFastElementsKind(); 846 ElementsKind elements_kind = GetInitialFastElementsKind();
709 bool has_double = false; 847 bool has_double = false;
(...skipping 686 matching lines...) Expand 10 before | Expand all | Expand 10 after
1396 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) 1534 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C)
1397 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) 1535 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A)
1398 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) 1536 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H)
1399 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) 1537 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A)
1400 #undef DEFINE_BUILTIN_ACCESSOR_C 1538 #undef DEFINE_BUILTIN_ACCESSOR_C
1401 #undef DEFINE_BUILTIN_ACCESSOR_A 1539 #undef DEFINE_BUILTIN_ACCESSOR_A
1402 1540
1403 1541
1404 } // namespace internal 1542 } // namespace internal
1405 } // namespace v8 1543 } // namespace v8
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