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