Chromium Code Reviews| Index: src/runtime.cc |
| diff --git a/src/runtime.cc b/src/runtime.cc |
| index 0046ff667ead130fd9bb19c70caf972d90e17cd4..db222a82b9f5ab2040766c28c17b1c8ebd527517 100644 |
| --- a/src/runtime.cc |
| +++ b/src/runtime.cc |
| @@ -685,7 +685,7 @@ void Runtime::SetupArrayBuffer(Isolate* isolate, |
| array_buffer->set_weak_next(isolate->heap()->array_buffers_list()); |
| isolate->heap()->set_array_buffers_list(*array_buffer); |
| - array_buffer->set_weak_first_array(isolate->heap()->undefined_value()); |
| + array_buffer->set_weak_first_view(isolate->heap()->undefined_value()); |
| } |
| @@ -850,8 +850,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitialize) { |
| Handle<Object> length_obj = isolate->factory()->NewNumberFromSize(length); |
| holder->set_length(*length_obj); |
| - holder->set_weak_next(buffer->weak_first_array()); |
| - buffer->set_weak_first_array(*holder); |
| + holder->set_weak_next(buffer->weak_first_view()); |
| + buffer->set_weak_first_view(*holder); |
| Handle<ExternalArray> elements = |
| isolate->factory()->NewExternalArray( |
| @@ -1003,6 +1003,226 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArraySetFastCases) { |
| } |
| +RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewInitialize) { |
| + HandleScope scope(isolate); |
| + ASSERT(args.length() == 4); |
| + CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0); |
| + CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 1); |
| + CONVERT_ARG_HANDLE_CHECKED(Object, byte_offset, 2); |
| + CONVERT_ARG_HANDLE_CHECKED(Object, byte_length, 3); |
| + |
| + holder->set_buffer(*buffer); |
| + ASSERT(byte_offset->IsNumber()); |
| + ASSERT( |
| + NumberToSize(isolate, buffer->byte_length()) >= |
| + NumberToSize(isolate, *byte_offset) |
| + + NumberToSize(isolate, *byte_length)); |
| + holder->set_byte_offset(*byte_offset); |
| + ASSERT(byte_length->IsNumber()); |
| + holder->set_byte_length(*byte_length); |
| + |
| + holder->set_weak_next(buffer->weak_first_view()); |
| + buffer->set_weak_first_view(*holder); |
| + |
| + return isolate->heap()->undefined_value(); |
| +} |
| + |
| + |
| +RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGetBuffer) { |
| + HandleScope scope(isolate); |
| + ASSERT(args.length() == 1); |
| + CONVERT_ARG_HANDLE_CHECKED(Object, holder, 0); |
| + Handle<JSDataView> data_view(JSDataView::cast(*holder)); |
|
rossberg
2013/06/21 12:25:53
You can just declare the type in the line above no
Dmitry Lomov (no reviews)
2013/06/21 12:39:20
Done.
|
| + return data_view->buffer(); |
| +} |
| + |
| + |
| +RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGetByteOffset) { |
| + HandleScope scope(isolate); |
| + ASSERT(args.length() == 1); |
| + CONVERT_ARG_HANDLE_CHECKED(Object, holder, 0); |
| + Handle<JSDataView> data_view(JSDataView::cast(*holder)); |
| + return data_view->byte_offset(); |
| +} |
| + |
| + |
| +RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGetByteLength) { |
| + HandleScope scope(isolate); |
| + ASSERT(args.length() == 1); |
| + CONVERT_ARG_HANDLE_CHECKED(Object, holder, 0); |
| + Handle<JSDataView> data_view(JSDataView::cast(*holder)); |
| + return data_view->byte_length(); |
| +} |
| + |
| + |
| +inline static bool NeedToFlipBytes(bool is_little_endian) { |
| +#ifdef V8_TARGET_LITTLE_ENDIAN |
| + return !is_little_endian; |
| +#else |
| + return is_little_endian; |
| +#endif |
| +} |
| + |
| + |
| +template<int n> |
| +inline void CopyBytes(uint8_t* target, uint8_t* source) { |
| + for (int i = 0; i < n; i++) { |
| + *(target++) = *(source++); |
| + } |
| +} |
| + |
| + |
| +template<int n> |
| +inline void FlipBytes(uint8_t* target, uint8_t* source) { |
| + source = source + (n-1); |
| + for (int i = 0; i < n; i++) { |
| + *(target++) = *(source--); |
| + } |
| +} |
| + |
| + |
| +template<typename T> |
| +inline static bool DataViewGetValue( |
| + Isolate* isolate, |
| + Handle<JSDataView> data_view, |
| + Handle<Object> byte_offset_obj, |
| + bool is_little_endian, |
| + T* result) { |
| + size_t byte_offset = NumberToSize(isolate, *byte_offset_obj); |
| + Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(data_view->buffer())); |
| + |
| + size_t data_view_byte_offset = |
| + NumberToSize(isolate, data_view->byte_offset()); |
| + size_t data_view_byte_length = |
| + NumberToSize(isolate, data_view->byte_length()); |
| + if (byte_offset + sizeof(T) > data_view_byte_length || |
| + byte_offset + sizeof(T) < byte_offset) { // overflow |
| + return false; |
| + } |
| + |
| + union Value { |
| + T data; |
| + uint8_t bytes[sizeof(T)]; |
| + }; |
| + |
| + Value value; |
| + size_t buffer_offset = data_view_byte_offset + byte_offset; |
| + ASSERT( |
| + NumberToSize(isolate, buffer->byte_length()) |
| + >= buffer_offset + sizeof(T)); |
| + uint8_t* source = |
| + static_cast<uint8_t*>(buffer->backing_store()) + buffer_offset; |
| + if (NeedToFlipBytes(is_little_endian)) { |
| + FlipBytes<sizeof(T)>(value.bytes, source); |
| + } else { |
| + CopyBytes<sizeof(T)>(value.bytes, source); |
| + } |
| + *result = value.data; |
| + return true; |
| +} |
| + |
| + |
| +template<typename T> |
| +static bool DataViewSetValue( |
| + Isolate* isolate, |
| + Handle<JSDataView> data_view, |
| + Handle<Object> byte_offset_obj, |
| + bool is_little_endian, |
| + T data) { |
| + size_t byte_offset = NumberToSize(isolate, *byte_offset_obj); |
| + Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(data_view->buffer())); |
| + |
| + size_t data_view_byte_offset = |
| + NumberToSize(isolate, data_view->byte_offset()); |
| + size_t data_view_byte_length = |
| + NumberToSize(isolate, data_view->byte_length()); |
| + if (byte_offset + sizeof(T) > data_view_byte_length || |
| + byte_offset + sizeof(T) < byte_offset) { // overflow |
| + return false; |
| + } |
| + |
| + union Value { |
| + T data; |
| + uint8_t bytes[sizeof(T)]; |
| + }; |
| + |
| + Value value; |
| + value.data = data; |
| + size_t buffer_offset = data_view_byte_offset + byte_offset; |
| + ASSERT( |
| + NumberToSize(isolate, buffer->byte_length()) |
| + >= buffer_offset + sizeof(T)); |
| + uint8_t* target = |
| + static_cast<uint8_t*>(buffer->backing_store()) + buffer_offset; |
| + if (NeedToFlipBytes(is_little_endian)) { |
| + FlipBytes<sizeof(T)>(target, value.bytes); |
| + } else { |
| + CopyBytes<sizeof(T)>(target, value.bytes); |
| + } |
| + return true; |
| +} |
| + |
| + |
| +#define DATA_VIEW_GETTER(TypeName, Type, Converter) \ |
| + RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGet##TypeName) { \ |
| + HandleScope scope(isolate); \ |
| + ASSERT(args.length() == 3); \ |
| + CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0); \ |
| + CONVERT_ARG_HANDLE_CHECKED(Object, offset, 1); \ |
| + CONVERT_BOOLEAN_ARG_CHECKED(is_little_endian, 2); \ |
| + Type result; \ |
| + if (DataViewGetValue( \ |
| + isolate, holder, offset, is_little_endian, &result)) { \ |
| + return isolate->heap()->Converter(result); \ |
| + } else { \ |
| + return isolate->Throw(*isolate->factory()->NewRangeError( \ |
| + "invalid_data_view_accessor_offset", \ |
| + HandleVector<Object>(NULL, 0))); \ |
| + } \ |
| + } |
| + |
| +DATA_VIEW_GETTER(Uint8, uint8_t, NumberFromUint32) |
| +DATA_VIEW_GETTER(Int8, int8_t, NumberFromInt32) |
| +DATA_VIEW_GETTER(Uint16, uint16_t, NumberFromUint32) |
| +DATA_VIEW_GETTER(Int16, int16_t, NumberFromInt32) |
| +DATA_VIEW_GETTER(Uint32, uint32_t, NumberFromUint32) |
| +DATA_VIEW_GETTER(Int32, int32_t, NumberFromInt32) |
| +DATA_VIEW_GETTER(Float32, float, NumberFromDouble) |
| +DATA_VIEW_GETTER(Float64, double, NumberFromDouble) |
| + |
| +#undef DATA_VIEW_GETTER |
| + |
| +#define DATA_VIEW_SETTER(TypeName, Type) \ |
| + RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewSet##TypeName) { \ |
| + HandleScope scope(isolate); \ |
| + ASSERT(args.length() == 4); \ |
| + CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0); \ |
| + CONVERT_ARG_HANDLE_CHECKED(Object, offset, 1); \ |
| + CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); \ |
| + CONVERT_BOOLEAN_ARG_CHECKED(is_little_endian, 3); \ |
| + Type v = static_cast<Type>(value->Number()); \ |
| + if (DataViewSetValue( \ |
| + isolate, holder, offset, is_little_endian, v)) { \ |
| + return isolate->heap()->undefined_value(); \ |
| + } else { \ |
| + return isolate->Throw(*isolate->factory()->NewRangeError( \ |
| + "invalid_data_view_accessor_offset", \ |
| + HandleVector<Object>(NULL, 0))); \ |
| + } \ |
| + } |
| + |
| +DATA_VIEW_SETTER(Uint8, uint8_t) |
| +DATA_VIEW_SETTER(Int8, int8_t) |
| +DATA_VIEW_SETTER(Uint16, uint16_t) |
| +DATA_VIEW_SETTER(Int16, int16_t) |
| +DATA_VIEW_SETTER(Uint32, uint32_t) |
| +DATA_VIEW_SETTER(Int32, int32_t) |
| +DATA_VIEW_SETTER(Float32, float) |
| +DATA_VIEW_SETTER(Float64, double) |
| + |
| +#undef DATA_VIEW_SETTER |
| + |
| + |
| RUNTIME_FUNCTION(MaybeObject*, Runtime_SetInitialize) { |
| HandleScope scope(isolate); |
| ASSERT(args.length() == 1); |