Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1121)

Unified Diff: src/runtime.cc

Issue 17153011: DataView implementation. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Self-review Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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);

Powered by Google App Engine
This is Rietveld 408576698