| 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 |