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) { | |
716 void* data; | 717 void* data; |
717 CHECK(V8::ArrayBufferAllocator() != NULL); | 718 CHECK(V8::ArrayBufferAllocator() != NULL); |
718 if (allocated_length != 0) { | 719 if (allocated_length != 0) { |
719 data = V8::ArrayBufferAllocator()->Allocate(allocated_length); | 720 if (initialize) { |
721 data = V8::ArrayBufferAllocator()->Allocate(allocated_length); | |
722 } else { | |
723 data = | |
724 V8::ArrayBufferAllocator()->AllocateUninitialized(allocated_length); | |
725 } | |
720 if (data == NULL) return false; | 726 if (data == NULL) return false; |
721 memset(data, 0, allocated_length); | |
722 } else { | 727 } else { |
723 data = NULL; | 728 data = NULL; |
724 } | 729 } |
725 | 730 |
726 SetupArrayBuffer(isolate, array_buffer, false, data, allocated_length); | 731 SetupArrayBuffer(isolate, array_buffer, false, data, allocated_length); |
727 | 732 |
728 isolate->heap()->AdjustAmountOfExternalAllocatedMemory(allocated_length); | 733 isolate->heap()->AdjustAmountOfExternalAllocatedMemory(allocated_length); |
729 | 734 |
730 return true; | 735 return true; |
731 } | 736 } |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
798 ARRAY_ID_INT8 = 2, | 803 ARRAY_ID_INT8 = 2, |
799 ARRAY_ID_UINT16 = 3, | 804 ARRAY_ID_UINT16 = 3, |
800 ARRAY_ID_INT16 = 4, | 805 ARRAY_ID_INT16 = 4, |
801 ARRAY_ID_UINT32 = 5, | 806 ARRAY_ID_UINT32 = 5, |
802 ARRAY_ID_INT32 = 6, | 807 ARRAY_ID_INT32 = 6, |
803 ARRAY_ID_FLOAT32 = 7, | 808 ARRAY_ID_FLOAT32 = 7, |
804 ARRAY_ID_FLOAT64 = 8, | 809 ARRAY_ID_FLOAT64 = 8, |
805 ARRAY_ID_UINT8C = 9 | 810 ARRAY_ID_UINT8C = 9 |
806 }; | 811 }; |
807 | 812 |
813 static void ArrayIdToTypeAndSize( | |
814 int arrayId, ExternalArrayType& array_type, size_t& element_size) { | |
Benedikt Meurer
2013/08/01 06:14:35
Use pointers instead of references.
| |
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 | |
808 | 857 |
809 RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitialize) { | 858 RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitialize) { |
810 HandleScope scope(isolate); | 859 HandleScope scope(isolate); |
811 ASSERT(args.length() == 5); | 860 ASSERT(args.length() == 5); |
812 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0); | 861 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0); |
813 CONVERT_SMI_ARG_CHECKED(arrayId, 1); | 862 CONVERT_SMI_ARG_CHECKED(arrayId, 1); |
814 CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 2); | 863 CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 2); |
815 CONVERT_ARG_HANDLE_CHECKED(Object, byte_offset_object, 3); | 864 CONVERT_ARG_HANDLE_CHECKED(Object, byte_offset_object, 3); |
816 CONVERT_ARG_HANDLE_CHECKED(Object, byte_length_object, 4); | 865 CONVERT_ARG_HANDLE_CHECKED(Object, byte_length_object, 4); |
817 | 866 |
818 ASSERT(holder->GetInternalFieldCount() == | 867 ASSERT(holder->GetInternalFieldCount() == |
819 v8::ArrayBufferView::kInternalFieldCount); | 868 v8::ArrayBufferView::kInternalFieldCount); |
820 for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) { | 869 for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) { |
821 holder->SetInternalField(i, Smi::FromInt(0)); | 870 holder->SetInternalField(i, Smi::FromInt(0)); |
822 } | 871 } |
823 | 872 |
824 ExternalArrayType arrayType; | 873 ExternalArrayType array_type; |
825 size_t elementSize; | 874 size_t element_size; |
826 switch (arrayId) { | 875 ArrayIdToTypeAndSize(arrayId, array_type, element_size); |
Benedikt Meurer
2013/08/01 06:14:35
Pointers for 2nd and 3rd argument.
| |
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 } | |
867 | 876 |
868 holder->set_buffer(*buffer); | 877 holder->set_buffer(*buffer); |
869 holder->set_byte_offset(*byte_offset_object); | 878 holder->set_byte_offset(*byte_offset_object); |
870 holder->set_byte_length(*byte_length_object); | 879 holder->set_byte_length(*byte_length_object); |
871 | 880 |
872 size_t byte_offset = NumberToSize(isolate, *byte_offset_object); | 881 size_t byte_offset = NumberToSize(isolate, *byte_offset_object); |
873 size_t byte_length = NumberToSize(isolate, *byte_length_object); | 882 size_t byte_length = NumberToSize(isolate, *byte_length_object); |
874 ASSERT(byte_length % elementSize == 0); | 883 ASSERT(byte_length % element_size == 0); |
875 size_t length = byte_length / elementSize; | 884 size_t length = byte_length / element_size; |
876 | 885 |
877 Handle<Object> length_obj = isolate->factory()->NewNumberFromSize(length); | 886 Handle<Object> length_obj = isolate->factory()->NewNumberFromSize(length); |
878 holder->set_length(*length_obj); | 887 holder->set_length(*length_obj); |
879 holder->set_weak_next(buffer->weak_first_view()); | 888 holder->set_weak_next(buffer->weak_first_view()); |
880 buffer->set_weak_first_view(*holder); | 889 buffer->set_weak_first_view(*holder); |
881 | 890 |
882 Handle<ExternalArray> elements = | 891 Handle<ExternalArray> elements = |
883 isolate->factory()->NewExternalArray( | 892 isolate->factory()->NewExternalArray( |
884 static_cast<int>(length), arrayType, | 893 static_cast<int>(length), array_type, |
885 static_cast<uint8_t*>(buffer->backing_store()) + byte_offset); | 894 static_cast<uint8_t*>(buffer->backing_store()) + byte_offset); |
886 holder->set_elements(*elements); | 895 holder->set_elements(*elements); |
887 return isolate->heap()->undefined_value(); | 896 return isolate->heap()->undefined_value(); |
888 } | 897 } |
889 | 898 |
890 | 899 |
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 sourec 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 | |
891 #define TYPED_ARRAY_GETTER(getter, accessor) \ | 986 #define TYPED_ARRAY_GETTER(getter, accessor) \ |
892 RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayGet##getter) { \ | 987 RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayGet##getter) { \ |
893 HandleScope scope(isolate); \ | 988 HandleScope scope(isolate); \ |
894 ASSERT(args.length() == 1); \ | 989 ASSERT(args.length() == 1); \ |
895 CONVERT_ARG_HANDLE_CHECKED(Object, holder, 0); \ | 990 CONVERT_ARG_HANDLE_CHECKED(Object, holder, 0); \ |
896 if (!holder->IsJSTypedArray()) \ | 991 if (!holder->IsJSTypedArray()) \ |
897 return isolate->Throw(*isolate->factory()->NewTypeError( \ | 992 return isolate->Throw(*isolate->factory()->NewTypeError( \ |
898 "not_typed_array", HandleVector<Object>(NULL, 0))); \ | 993 "not_typed_array", HandleVector<Object>(NULL, 0))); \ |
899 Handle<JSTypedArray> typed_array(JSTypedArray::cast(*holder)); \ | 994 Handle<JSTypedArray> typed_array(JSTypedArray::cast(*holder)); \ |
900 return typed_array->accessor(); \ | 995 return typed_array->accessor(); \ |
(...skipping 12957 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
13858 // Handle last resort GC and make sure to allow future allocations | 13953 // Handle last resort GC and make sure to allow future allocations |
13859 // to grow the heap without causing GCs (if possible). | 13954 // to grow the heap without causing GCs (if possible). |
13860 isolate->counters()->gc_last_resort_from_js()->Increment(); | 13955 isolate->counters()->gc_last_resort_from_js()->Increment(); |
13861 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, | 13956 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, |
13862 "Runtime::PerformGC"); | 13957 "Runtime::PerformGC"); |
13863 } | 13958 } |
13864 } | 13959 } |
13865 | 13960 |
13866 | 13961 |
13867 } } // namespace v8::internal | 13962 } } // namespace v8::internal |
OLD | NEW |