Index: src/runtime.cc |
diff --git a/src/runtime.cc b/src/runtime.cc |
index 0046ff667ead130fd9bb19c70caf972d90e17cd4..863514babdf4ca9f6f288229d5e4bc3e356df65f 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,223 @@ 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(JSDataView, data_view, 0); |
+ return data_view->buffer(); |
+} |
+ |
+ |
+RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGetByteOffset) { |
+ HandleScope scope(isolate); |
+ ASSERT(args.length() == 1); |
+ CONVERT_ARG_HANDLE_CHECKED(JSDataView, data_view, 0); |
+ return data_view->byte_offset(); |
+} |
+ |
+ |
+RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGetByteLength) { |
+ HandleScope scope(isolate); |
+ ASSERT(args.length() == 1); |
+ CONVERT_ARG_HANDLE_CHECKED(JSDataView, data_view, 0); |
+ 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); |