Index: src/runtime.cc |
diff --git a/src/runtime.cc b/src/runtime.cc |
index 2cbaad10fc8566914961340cbb9a9889c47cede1..f097a0802eaee9900d125829d9ddb879051ad30a 100644 |
--- a/src/runtime.cc |
+++ b/src/runtime.cc |
@@ -712,13 +712,18 @@ void Runtime::SetupArrayBuffer(Isolate* isolate, |
bool Runtime::SetupArrayBufferAllocatingData( |
Isolate* isolate, |
Handle<JSArrayBuffer> array_buffer, |
- size_t allocated_length) { |
+ size_t allocated_length, |
+ bool initialize) { |
void* data; |
CHECK(V8::ArrayBufferAllocator() != NULL); |
if (allocated_length != 0) { |
- data = V8::ArrayBufferAllocator()->Allocate(allocated_length); |
+ if (initialize) { |
+ data = V8::ArrayBufferAllocator()->Allocate(allocated_length); |
+ } else { |
+ data = |
+ V8::ArrayBufferAllocator()->AllocateUninitialized(allocated_length); |
+ } |
if (data == NULL) return false; |
- memset(data, 0, allocated_length); |
} else { |
data = NULL; |
} |
@@ -805,65 +810,69 @@ enum TypedArrayId { |
ARRAY_ID_UINT8C = 9 |
}; |
- |
-RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitialize) { |
- HandleScope scope(isolate); |
- ASSERT(args.length() == 5); |
- CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0); |
- CONVERT_SMI_ARG_CHECKED(arrayId, 1); |
- CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 2); |
- CONVERT_ARG_HANDLE_CHECKED(Object, byte_offset_object, 3); |
- CONVERT_ARG_HANDLE_CHECKED(Object, byte_length_object, 4); |
- |
- ASSERT(holder->GetInternalFieldCount() == |
- v8::ArrayBufferView::kInternalFieldCount); |
- for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) { |
- holder->SetInternalField(i, Smi::FromInt(0)); |
- } |
- |
- ExternalArrayType arrayType; |
- size_t elementSize; |
+static void ArrayIdToTypeAndSize( |
+ int arrayId, ExternalArrayType* array_type, size_t* element_size) { |
switch (arrayId) { |
case ARRAY_ID_UINT8: |
- arrayType = kExternalUnsignedByteArray; |
- elementSize = 1; |
+ *array_type = kExternalUnsignedByteArray; |
+ *element_size = 1; |
break; |
case ARRAY_ID_INT8: |
- arrayType = kExternalByteArray; |
- elementSize = 1; |
+ *array_type = kExternalByteArray; |
+ *element_size = 1; |
break; |
case ARRAY_ID_UINT16: |
- arrayType = kExternalUnsignedShortArray; |
- elementSize = 2; |
+ *array_type = kExternalUnsignedShortArray; |
+ *element_size = 2; |
break; |
case ARRAY_ID_INT16: |
- arrayType = kExternalShortArray; |
- elementSize = 2; |
+ *array_type = kExternalShortArray; |
+ *element_size = 2; |
break; |
case ARRAY_ID_UINT32: |
- arrayType = kExternalUnsignedIntArray; |
- elementSize = 4; |
+ *array_type = kExternalUnsignedIntArray; |
+ *element_size = 4; |
break; |
case ARRAY_ID_INT32: |
- arrayType = kExternalIntArray; |
- elementSize = 4; |
+ *array_type = kExternalIntArray; |
+ *element_size = 4; |
break; |
case ARRAY_ID_FLOAT32: |
- arrayType = kExternalFloatArray; |
- elementSize = 4; |
+ *array_type = kExternalFloatArray; |
+ *element_size = 4; |
break; |
case ARRAY_ID_FLOAT64: |
- arrayType = kExternalDoubleArray; |
- elementSize = 8; |
+ *array_type = kExternalDoubleArray; |
+ *element_size = 8; |
break; |
case ARRAY_ID_UINT8C: |
- arrayType = kExternalPixelArray; |
- elementSize = 1; |
+ *array_type = kExternalPixelArray; |
+ *element_size = 1; |
break; |
default: |
UNREACHABLE(); |
- return NULL; |
} |
+} |
+ |
+ |
+RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitialize) { |
+ HandleScope scope(isolate); |
+ ASSERT(args.length() == 5); |
+ CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0); |
+ CONVERT_SMI_ARG_CHECKED(arrayId, 1); |
+ CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 2); |
+ CONVERT_ARG_HANDLE_CHECKED(Object, byte_offset_object, 3); |
+ CONVERT_ARG_HANDLE_CHECKED(Object, byte_length_object, 4); |
+ |
+ ASSERT(holder->GetInternalFieldCount() == |
+ v8::ArrayBufferView::kInternalFieldCount); |
+ for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) { |
+ holder->SetInternalField(i, Smi::FromInt(0)); |
+ } |
+ |
+ ExternalArrayType array_type; |
+ size_t element_size; |
+ ArrayIdToTypeAndSize(arrayId, &array_type, &element_size); |
holder->set_buffer(*buffer); |
holder->set_byte_offset(*byte_offset_object); |
@@ -871,8 +880,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitialize) { |
size_t byte_offset = NumberToSize(isolate, *byte_offset_object); |
size_t byte_length = NumberToSize(isolate, *byte_length_object); |
- ASSERT(byte_length % elementSize == 0); |
- size_t length = byte_length / elementSize; |
+ ASSERT(byte_length % element_size == 0); |
+ size_t length = byte_length / element_size; |
Handle<Object> length_obj = isolate->factory()->NewNumberFromSize(length); |
holder->set_length(*length_obj); |
@@ -881,13 +890,99 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitialize) { |
Handle<ExternalArray> elements = |
isolate->factory()->NewExternalArray( |
- static_cast<int>(length), arrayType, |
+ static_cast<int>(length), array_type, |
static_cast<uint8_t*>(buffer->backing_store()) + byte_offset); |
holder->set_elements(*elements); |
return isolate->heap()->undefined_value(); |
} |
+// Initializes a typed array from an array-like object. |
+// If an array-like object happens to be a typed array of the same type, |
+// initializes backing store using memove. |
+// |
+// Returns true if backing store was initialized or false otherwise. |
+RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitializeFromArrayLike) { |
+ HandleScope scope(isolate); |
+ ASSERT(args.length() == 4); |
+ CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0); |
+ CONVERT_SMI_ARG_CHECKED(arrayId, 1); |
+ CONVERT_ARG_HANDLE_CHECKED(Object, source, 2); |
+ CONVERT_ARG_HANDLE_CHECKED(Object, length_obj, 3); |
+ |
+ ASSERT(holder->GetInternalFieldCount() == |
+ v8::ArrayBufferView::kInternalFieldCount); |
+ for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) { |
+ holder->SetInternalField(i, Smi::FromInt(0)); |
+ } |
+ |
+ ExternalArrayType array_type; |
+ size_t element_size; |
+ ArrayIdToTypeAndSize(arrayId, &array_type, &element_size); |
+ |
+ Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer(); |
+ size_t length = NumberToSize(isolate, *length_obj); |
+ size_t byte_length = length * element_size; |
+ if (byte_length < length) { // Overflow |
+ return isolate->Throw(*isolate->factory()-> |
+ NewRangeError("invalid_array_buffer_length", |
+ HandleVector<Object>(NULL, 0))); |
+ } |
+ |
+ // We assume that the caller of this function will initialize holder |
+ // with the loop |
+ // for(i = 0; i < length; i++) { holder[i] = source[i]; } |
+ // If source is a typed array, this loop will always run to completion, |
+ // so we are sure that the backing store will be initialized. |
+ // Otherwise, we do not know (the indexing operation might throw). |
+ // Hence we require zero initialization unless our sourec is a typed array. |
+ bool should_zero_initialize = !source->IsJSTypedArray(); |
+ |
+ if (!Runtime::SetupArrayBufferAllocatingData( |
+ isolate, buffer, byte_length, should_zero_initialize)) { |
+ return isolate->Throw(*isolate->factory()-> |
+ NewRangeError("invalid_array_buffer_length", |
+ HandleVector<Object>(NULL, 0))); |
+ } |
+ |
+ holder->set_buffer(*buffer); |
+ holder->set_byte_offset(Smi::FromInt(0)); |
+ Handle<Object> byte_length_obj( |
+ isolate->factory()->NewNumberFromSize(byte_length)); |
+ holder->set_byte_length(*byte_length_obj); |
+ holder->set_length(*length_obj); |
+ holder->set_weak_next(buffer->weak_first_view()); |
+ buffer->set_weak_first_view(*holder); |
+ |
+ Handle<ExternalArray> elements = |
+ isolate->factory()->NewExternalArray( |
+ static_cast<int>(length), array_type, |
+ static_cast<uint8_t*>(buffer->backing_store())); |
+ holder->set_elements(*elements); |
+ |
+ if (source->IsJSTypedArray()) { |
+ Handle<JSTypedArray> typed_array(JSTypedArray::cast(*source)); |
+ |
+ if (typed_array->type() == holder->type()) { |
+ uint8_t* backing_store = |
+ static_cast<uint8_t*>( |
+ JSArrayBuffer::cast(typed_array->buffer())->backing_store()); |
+ size_t source_byte_offset = |
+ NumberToSize(isolate, typed_array->byte_offset()); |
+ OS::MemCopy( |
+ buffer->backing_store(), |
+ backing_store + source_byte_offset, |
+ byte_length); |
+ return *isolate->factory()->true_value(); |
+ } else { |
+ return *isolate->factory()->false_value(); |
+ } |
+ } |
+ |
+ return *isolate->factory()->false_value(); |
+} |
+ |
+ |
#define TYPED_ARRAY_GETTER(getter, accessor) \ |
RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayGet##getter) { \ |
HandleScope scope(isolate); \ |