Chromium Code Reviews| Index: src/runtime.cc |
| diff --git a/src/runtime.cc b/src/runtime.cc |
| index 0046ff667ead130fd9bb19c70caf972d90e17cd4..966e6cce1c9f37dfa2c43fc15af19ab4f760cc69 100644 |
| --- a/src/runtime.cc |
| +++ b/src/runtime.cc |
| @@ -1003,6 +1003,256 @@ 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_array()); |
| + buffer->set_weak_first_array(*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); |
| + if (!holder->IsJSDataView()) { |
|
rossberg
2013/06/21 08:44:01
Why not move this check to the JavaScript side? (h
Dmitry Lomov (no reviews)
2013/06/21 11:32:10
Done.
|
| + return isolate->Throw(*isolate->factory()->NewTypeError( |
| + "not_data_view", HandleVector<Object>(NULL, 0))); |
| + } |
| + Handle<JSDataView> data_view(JSDataView::cast(*holder)); |
| + return data_view->buffer(); |
| +} |
| + |
| + |
| +RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGetByteOffset) { |
| + HandleScope scope(isolate); |
| + ASSERT(args.length() == 1); |
| + CONVERT_ARG_HANDLE_CHECKED(Object, holder, 0); |
| + if (!holder->IsJSDataView()) { |
| + return isolate->Throw(*isolate->factory()->NewTypeError( |
| + "not_data_view", HandleVector<Object>(NULL, 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); |
| + if (!holder->IsJSDataView()) { |
| + return isolate->Throw(*isolate->factory()->NewTypeError( |
| + "not_data_view", HandleVector<Object>(NULL, 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 |
| +} |
| + |
| + |
| +inline void SwapBytes(uint8_t* p, uint8_t* q) { |
| + uint8_t temp = *p; |
|
rossberg
2013/06/21 08:44:01
Nit: indentation
Dmitry Lomov (no reviews)
2013/06/21 11:32:10
Done.
|
| + *p = *q; |
| + *q = temp; |
| +} |
| + |
| + |
| +template<int n> |
| +void FlipBytes(uint8_t* p, bool is_little_endian); |
| + |
| + |
| +template<> |
| +void FlipBytes<1>(uint8_t*, bool) {} |
| + |
| + |
| +template<> |
| +void FlipBytes<2>(uint8_t* p, bool is_little_endian) { |
| + if (!NeedToFlipBytes(is_little_endian)) return; |
| + SwapBytes(p, p+1); |
| +} |
| + |
| + |
| +template<> |
| +void FlipBytes<4>(uint8_t* p, bool is_little_endian) { |
| + if (!NeedToFlipBytes(is_little_endian)) return; |
| + SwapBytes(p+1, p+2); |
| + SwapBytes(p, p+3); |
| +} |
| + |
| + |
| +template<> |
| +void FlipBytes<8>(uint8_t* p, bool is_little_endian) { |
| + if (!NeedToFlipBytes(is_little_endian)) return; |
| + SwapBytes(p+3, p+4); |
| + SwapBytes(p+2, p+5); |
| + SwapBytes(p+1, p+6); |
| + SwapBytes(p, p+7); |
| +} |
| + |
| + |
| +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; |
|
rossberg
2013/06/21 08:44:01
Nit: indentation
Dmitry Lomov (no reviews)
2013/06/21 11:32:10
Done. Didn't move this to v8utils.h, because it lo
|
| + 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)); |
| + OS::MemCopy(value.bytes, |
|
rossberg
2013/06/21 08:44:01
OS::MemCopy seems overkill here. Use at least the
Dmitry Lomov (no reviews)
2013/06/21 11:32:10
Done.
|
| + static_cast<uint8_t*>(buffer->backing_store()) + buffer_offset, |
| + sizeof(T)); |
| + FlipBytes<sizeof(T)>(value.bytes, is_little_endian); |
| + *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; |
|
rossberg
2013/06/21 08:44:01
Nit: indentation
Dmitry Lomov (no reviews)
2013/06/21 11:32:10
Done.
|
| + 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)); |
| + FlipBytes<sizeof(T)>(value.bytes, is_little_endian); |
| + OS::MemCopy( |
| + static_cast<uint8_t*>(buffer->backing_store()) + buffer_offset, |
| + value.bytes, |
| + sizeof(T)); |
| + return true; |
| +} |
| + |
| + |
| +#define DATA_VIEW_GETTER(TypeName, Type, Convertor) \ |
|
rossberg
2013/06/21 08:44:01
Nit: I think the spelling is Converter
Dmitry Lomov (no reviews)
2013/06/21 11:32:10
Done.
Dmitry Lomov (no reviews)
2013/06/21 11:32:10
Done.
|
| + 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()->Convertor(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); |