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) { |
| 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); |
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 |