OLD | NEW |
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 694 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
705 | 705 |
706 array_buffer->set_weak_next(isolate->heap()->array_buffers_list()); | 706 array_buffer->set_weak_next(isolate->heap()->array_buffers_list()); |
707 isolate->heap()->set_array_buffers_list(*array_buffer); | 707 isolate->heap()->set_array_buffers_list(*array_buffer); |
708 array_buffer->set_weak_first_view(isolate->heap()->undefined_value()); | 708 array_buffer->set_weak_first_view(isolate->heap()->undefined_value()); |
709 } | 709 } |
710 | 710 |
711 | 711 |
712 bool Runtime::SetupArrayBufferAllocatingData( | 712 bool Runtime::SetupArrayBufferAllocatingData( |
713 Isolate* isolate, | 713 Isolate* isolate, |
714 Handle<JSArrayBuffer> array_buffer, | 714 Handle<JSArrayBuffer> array_buffer, |
715 size_t allocated_length, | 715 size_t allocated_length) { |
716 bool initialize) { | |
717 void* data; | 716 void* data; |
718 CHECK(V8::ArrayBufferAllocator() != NULL); | 717 CHECK(V8::ArrayBufferAllocator() != NULL); |
719 if (allocated_length != 0) { | 718 if (allocated_length != 0) { |
720 if (initialize) { | 719 data = V8::ArrayBufferAllocator()->Allocate(allocated_length); |
721 data = V8::ArrayBufferAllocator()->Allocate(allocated_length); | |
722 } else { | |
723 data = | |
724 V8::ArrayBufferAllocator()->AllocateUninitialized(allocated_length); | |
725 } | |
726 if (data == NULL) return false; | 720 if (data == NULL) return false; |
| 721 memset(data, 0, allocated_length); |
727 } else { | 722 } else { |
728 data = NULL; | 723 data = NULL; |
729 } | 724 } |
730 | 725 |
731 SetupArrayBuffer(isolate, array_buffer, false, data, allocated_length); | 726 SetupArrayBuffer(isolate, array_buffer, false, data, allocated_length); |
732 | 727 |
733 isolate->heap()->AdjustAmountOfExternalAllocatedMemory(allocated_length); | 728 isolate->heap()->AdjustAmountOfExternalAllocatedMemory(allocated_length); |
734 | 729 |
735 return true; | 730 return true; |
736 } | 731 } |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
803 ARRAY_ID_INT8 = 2, | 798 ARRAY_ID_INT8 = 2, |
804 ARRAY_ID_UINT16 = 3, | 799 ARRAY_ID_UINT16 = 3, |
805 ARRAY_ID_INT16 = 4, | 800 ARRAY_ID_INT16 = 4, |
806 ARRAY_ID_UINT32 = 5, | 801 ARRAY_ID_UINT32 = 5, |
807 ARRAY_ID_INT32 = 6, | 802 ARRAY_ID_INT32 = 6, |
808 ARRAY_ID_FLOAT32 = 7, | 803 ARRAY_ID_FLOAT32 = 7, |
809 ARRAY_ID_FLOAT64 = 8, | 804 ARRAY_ID_FLOAT64 = 8, |
810 ARRAY_ID_UINT8C = 9 | 805 ARRAY_ID_UINT8C = 9 |
811 }; | 806 }; |
812 | 807 |
813 static void ArrayIdToTypeAndSize( | |
814 int arrayId, ExternalArrayType* array_type, size_t* element_size) { | |
815 switch (arrayId) { | |
816 case ARRAY_ID_UINT8: | |
817 *array_type = kExternalUnsignedByteArray; | |
818 *element_size = 1; | |
819 break; | |
820 case ARRAY_ID_INT8: | |
821 *array_type = kExternalByteArray; | |
822 *element_size = 1; | |
823 break; | |
824 case ARRAY_ID_UINT16: | |
825 *array_type = kExternalUnsignedShortArray; | |
826 *element_size = 2; | |
827 break; | |
828 case ARRAY_ID_INT16: | |
829 *array_type = kExternalShortArray; | |
830 *element_size = 2; | |
831 break; | |
832 case ARRAY_ID_UINT32: | |
833 *array_type = kExternalUnsignedIntArray; | |
834 *element_size = 4; | |
835 break; | |
836 case ARRAY_ID_INT32: | |
837 *array_type = kExternalIntArray; | |
838 *element_size = 4; | |
839 break; | |
840 case ARRAY_ID_FLOAT32: | |
841 *array_type = kExternalFloatArray; | |
842 *element_size = 4; | |
843 break; | |
844 case ARRAY_ID_FLOAT64: | |
845 *array_type = kExternalDoubleArray; | |
846 *element_size = 8; | |
847 break; | |
848 case ARRAY_ID_UINT8C: | |
849 *array_type = kExternalPixelArray; | |
850 *element_size = 1; | |
851 break; | |
852 default: | |
853 UNREACHABLE(); | |
854 } | |
855 } | |
856 | |
857 | 808 |
858 RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitialize) { | 809 RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitialize) { |
859 HandleScope scope(isolate); | 810 HandleScope scope(isolate); |
860 ASSERT(args.length() == 5); | 811 ASSERT(args.length() == 5); |
861 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0); | 812 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0); |
862 CONVERT_SMI_ARG_CHECKED(arrayId, 1); | 813 CONVERT_SMI_ARG_CHECKED(arrayId, 1); |
863 CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 2); | 814 CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 2); |
864 CONVERT_ARG_HANDLE_CHECKED(Object, byte_offset_object, 3); | 815 CONVERT_ARG_HANDLE_CHECKED(Object, byte_offset_object, 3); |
865 CONVERT_ARG_HANDLE_CHECKED(Object, byte_length_object, 4); | 816 CONVERT_ARG_HANDLE_CHECKED(Object, byte_length_object, 4); |
866 | 817 |
867 ASSERT(holder->GetInternalFieldCount() == | 818 ASSERT(holder->GetInternalFieldCount() == |
868 v8::ArrayBufferView::kInternalFieldCount); | 819 v8::ArrayBufferView::kInternalFieldCount); |
869 for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) { | 820 for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) { |
870 holder->SetInternalField(i, Smi::FromInt(0)); | 821 holder->SetInternalField(i, Smi::FromInt(0)); |
871 } | 822 } |
872 | 823 |
873 ExternalArrayType array_type; | 824 ExternalArrayType arrayType; |
874 size_t element_size; | 825 size_t elementSize; |
875 ArrayIdToTypeAndSize(arrayId, &array_type, &element_size); | 826 switch (arrayId) { |
| 827 case ARRAY_ID_UINT8: |
| 828 arrayType = kExternalUnsignedByteArray; |
| 829 elementSize = 1; |
| 830 break; |
| 831 case ARRAY_ID_INT8: |
| 832 arrayType = kExternalByteArray; |
| 833 elementSize = 1; |
| 834 break; |
| 835 case ARRAY_ID_UINT16: |
| 836 arrayType = kExternalUnsignedShortArray; |
| 837 elementSize = 2; |
| 838 break; |
| 839 case ARRAY_ID_INT16: |
| 840 arrayType = kExternalShortArray; |
| 841 elementSize = 2; |
| 842 break; |
| 843 case ARRAY_ID_UINT32: |
| 844 arrayType = kExternalUnsignedIntArray; |
| 845 elementSize = 4; |
| 846 break; |
| 847 case ARRAY_ID_INT32: |
| 848 arrayType = kExternalIntArray; |
| 849 elementSize = 4; |
| 850 break; |
| 851 case ARRAY_ID_FLOAT32: |
| 852 arrayType = kExternalFloatArray; |
| 853 elementSize = 4; |
| 854 break; |
| 855 case ARRAY_ID_FLOAT64: |
| 856 arrayType = kExternalDoubleArray; |
| 857 elementSize = 8; |
| 858 break; |
| 859 case ARRAY_ID_UINT8C: |
| 860 arrayType = kExternalPixelArray; |
| 861 elementSize = 1; |
| 862 break; |
| 863 default: |
| 864 UNREACHABLE(); |
| 865 return NULL; |
| 866 } |
876 | 867 |
877 holder->set_buffer(*buffer); | 868 holder->set_buffer(*buffer); |
878 holder->set_byte_offset(*byte_offset_object); | 869 holder->set_byte_offset(*byte_offset_object); |
879 holder->set_byte_length(*byte_length_object); | 870 holder->set_byte_length(*byte_length_object); |
880 | 871 |
881 size_t byte_offset = NumberToSize(isolate, *byte_offset_object); | 872 size_t byte_offset = NumberToSize(isolate, *byte_offset_object); |
882 size_t byte_length = NumberToSize(isolate, *byte_length_object); | 873 size_t byte_length = NumberToSize(isolate, *byte_length_object); |
883 ASSERT(byte_length % element_size == 0); | 874 ASSERT(byte_length % elementSize == 0); |
884 size_t length = byte_length / element_size; | 875 size_t length = byte_length / elementSize; |
885 | 876 |
886 Handle<Object> length_obj = isolate->factory()->NewNumberFromSize(length); | 877 Handle<Object> length_obj = isolate->factory()->NewNumberFromSize(length); |
887 holder->set_length(*length_obj); | 878 holder->set_length(*length_obj); |
888 holder->set_weak_next(buffer->weak_first_view()); | 879 holder->set_weak_next(buffer->weak_first_view()); |
889 buffer->set_weak_first_view(*holder); | 880 buffer->set_weak_first_view(*holder); |
890 | 881 |
891 Handle<ExternalArray> elements = | 882 Handle<ExternalArray> elements = |
892 isolate->factory()->NewExternalArray( | 883 isolate->factory()->NewExternalArray( |
893 static_cast<int>(length), array_type, | 884 static_cast<int>(length), arrayType, |
894 static_cast<uint8_t*>(buffer->backing_store()) + byte_offset); | 885 static_cast<uint8_t*>(buffer->backing_store()) + byte_offset); |
895 holder->set_elements(*elements); | 886 holder->set_elements(*elements); |
896 return isolate->heap()->undefined_value(); | 887 return isolate->heap()->undefined_value(); |
897 } | 888 } |
898 | 889 |
899 | 890 |
900 // Initializes a typed array from an array-like object. | |
901 // If an array-like object happens to be a typed array of the same type, | |
902 // initializes backing store using memove. | |
903 // | |
904 // Returns true if backing store was initialized or false otherwise. | |
905 RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitializeFromArrayLike) { | |
906 HandleScope scope(isolate); | |
907 ASSERT(args.length() == 4); | |
908 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0); | |
909 CONVERT_SMI_ARG_CHECKED(arrayId, 1); | |
910 CONVERT_ARG_HANDLE_CHECKED(Object, source, 2); | |
911 CONVERT_ARG_HANDLE_CHECKED(Object, length_obj, 3); | |
912 | |
913 ASSERT(holder->GetInternalFieldCount() == | |
914 v8::ArrayBufferView::kInternalFieldCount); | |
915 for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) { | |
916 holder->SetInternalField(i, Smi::FromInt(0)); | |
917 } | |
918 | |
919 ExternalArrayType array_type; | |
920 size_t element_size; | |
921 ArrayIdToTypeAndSize(arrayId, &array_type, &element_size); | |
922 | |
923 Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer(); | |
924 size_t length = NumberToSize(isolate, *length_obj); | |
925 size_t byte_length = length * element_size; | |
926 if (byte_length < length) { // Overflow | |
927 return isolate->Throw(*isolate->factory()-> | |
928 NewRangeError("invalid_array_buffer_length", | |
929 HandleVector<Object>(NULL, 0))); | |
930 } | |
931 | |
932 // We assume that the caller of this function will initialize holder | |
933 // with the loop | |
934 // for(i = 0; i < length; i++) { holder[i] = source[i]; } | |
935 // If source is a typed array, this loop will always run to completion, | |
936 // so we are sure that the backing store will be initialized. | |
937 // Otherwise, we do not know (the indexing operation might throw). | |
938 // Hence we require zero initialization unless our source is a typed array. | |
939 bool should_zero_initialize = !source->IsJSTypedArray(); | |
940 | |
941 if (!Runtime::SetupArrayBufferAllocatingData( | |
942 isolate, buffer, byte_length, should_zero_initialize)) { | |
943 return isolate->Throw(*isolate->factory()-> | |
944 NewRangeError("invalid_array_buffer_length", | |
945 HandleVector<Object>(NULL, 0))); | |
946 } | |
947 | |
948 holder->set_buffer(*buffer); | |
949 holder->set_byte_offset(Smi::FromInt(0)); | |
950 Handle<Object> byte_length_obj( | |
951 isolate->factory()->NewNumberFromSize(byte_length)); | |
952 holder->set_byte_length(*byte_length_obj); | |
953 holder->set_length(*length_obj); | |
954 holder->set_weak_next(buffer->weak_first_view()); | |
955 buffer->set_weak_first_view(*holder); | |
956 | |
957 Handle<ExternalArray> elements = | |
958 isolate->factory()->NewExternalArray( | |
959 static_cast<int>(length), array_type, | |
960 static_cast<uint8_t*>(buffer->backing_store())); | |
961 holder->set_elements(*elements); | |
962 | |
963 if (source->IsJSTypedArray()) { | |
964 Handle<JSTypedArray> typed_array(JSTypedArray::cast(*source)); | |
965 | |
966 if (typed_array->type() == holder->type()) { | |
967 uint8_t* backing_store = | |
968 static_cast<uint8_t*>( | |
969 JSArrayBuffer::cast(typed_array->buffer())->backing_store()); | |
970 size_t source_byte_offset = | |
971 NumberToSize(isolate, typed_array->byte_offset()); | |
972 OS::MemCopy( | |
973 buffer->backing_store(), | |
974 backing_store + source_byte_offset, | |
975 byte_length); | |
976 return *isolate->factory()->true_value(); | |
977 } else { | |
978 return *isolate->factory()->false_value(); | |
979 } | |
980 } | |
981 | |
982 return *isolate->factory()->false_value(); | |
983 } | |
984 | |
985 | |
986 #define TYPED_ARRAY_GETTER(getter, accessor) \ | 891 #define TYPED_ARRAY_GETTER(getter, accessor) \ |
987 RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayGet##getter) { \ | 892 RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayGet##getter) { \ |
988 HandleScope scope(isolate); \ | 893 HandleScope scope(isolate); \ |
989 ASSERT(args.length() == 1); \ | 894 ASSERT(args.length() == 1); \ |
990 CONVERT_ARG_HANDLE_CHECKED(Object, holder, 0); \ | 895 CONVERT_ARG_HANDLE_CHECKED(Object, holder, 0); \ |
991 if (!holder->IsJSTypedArray()) \ | 896 if (!holder->IsJSTypedArray()) \ |
992 return isolate->Throw(*isolate->factory()->NewTypeError( \ | 897 return isolate->Throw(*isolate->factory()->NewTypeError( \ |
993 "not_typed_array", HandleVector<Object>(NULL, 0))); \ | 898 "not_typed_array", HandleVector<Object>(NULL, 0))); \ |
994 Handle<JSTypedArray> typed_array(JSTypedArray::cast(*holder)); \ | 899 Handle<JSTypedArray> typed_array(JSTypedArray::cast(*holder)); \ |
995 return typed_array->accessor(); \ | 900 return typed_array->accessor(); \ |
(...skipping 12957 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13953 // Handle last resort GC and make sure to allow future allocations | 13858 // Handle last resort GC and make sure to allow future allocations |
13954 // to grow the heap without causing GCs (if possible). | 13859 // to grow the heap without causing GCs (if possible). |
13955 isolate->counters()->gc_last_resort_from_js()->Increment(); | 13860 isolate->counters()->gc_last_resort_from_js()->Increment(); |
13956 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, | 13861 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, |
13957 "Runtime::PerformGC"); | 13862 "Runtime::PerformGC"); |
13958 } | 13863 } |
13959 } | 13864 } |
13960 | 13865 |
13961 | 13866 |
13962 } } // namespace v8::internal | 13867 } } // namespace v8::internal |
OLD | NEW |