Chromium Code Reviews| Index: runtime/vm/dart_api_message.cc |
| diff --git a/runtime/vm/dart_api_message.cc b/runtime/vm/dart_api_message.cc |
| index 5315301baef99a21bf587b324ed0342745bd06ad..4fc8e3e3526930bb45de5cd40030b667cb7288c8 100644 |
| --- a/runtime/vm/dart_api_message.cc |
| +++ b/runtime/vm/dart_api_message.cc |
| @@ -125,16 +125,35 @@ Dart_CObject* ApiMessageReader::AllocateDartCObjectString(intptr_t length) { |
| } |
| -Dart_CObject* ApiMessageReader::AllocateDartCObjectUint8Array(intptr_t length) { |
| +static int SizeInBytes(Dart_CObject::ByteArrayType type) { |
| + switch (type) { |
| + case Dart_CObject::kInt8Array: |
| + case Dart_CObject::kUint8Array: |
| + return 1; |
| + case Dart_CObject::kInt16Array: |
| + case Dart_CObject::kUint16Array: |
| + return 2; |
| + default: |
| + break; |
| + } |
| + UNREACHABLE(); |
| + return -1; |
| +} |
| + |
| + |
| +Dart_CObject* ApiMessageReader::AllocateDartCObjectByteArray( |
| + Dart_CObject::ByteArrayType type, intptr_t length) { |
| // Allocate a Dart_CObject structure followed by an array of bytes |
| // for the byte array content. The pointer to the byte array content |
| // is set up to this area. |
| + intptr_t length_in_bytes = SizeInBytes(type) * length; |
| Dart_CObject* value = |
| reinterpret_cast<Dart_CObject*>( |
| - alloc_(NULL, 0, sizeof(Dart_CObject) + length)); |
| + alloc_(NULL, 0, sizeof(Dart_CObject) + length_in_bytes)); |
| ASSERT(value != NULL); |
| - value->type = Dart_CObject::kUint8Array; |
| - value->value.as_array.length = length; |
| + value->type = Dart_CObject::kByteArray; |
| + value->value.as_byte_array.type = type; |
| + value->value.as_byte_array.length = length_in_bytes; |
| if (length > 0) { |
| value->value.as_byte_array.values = |
| reinterpret_cast<uint8_t*>(value) + sizeof(*value); |
| @@ -191,6 +210,55 @@ ApiMessageReader::BackRefNode* ApiMessageReader::AllocateBackRefNode( |
| } |
| +static Dart_CObject::ByteArrayType GetByteArrayTypeFromView( |
| + Dart_CObject_Internal* object) { |
| + struct { |
| + const char* name; |
| + Dart_CObject::ByteArrayType type; |
| + } view_class_names[] = { |
| + { "_Int8ArrayView", Dart_CObject::kInt8Array }, |
| + { "_Uint8ArrayView", Dart_CObject::kUint8Array }, |
| + { "_Int16ArrayView", Dart_CObject::kInt16Array }, |
| + { "_Uint16ArrayView", Dart_CObject::kUint16Array }, |
| + { NULL, Dart_CObject::kNumberOfByteArrayTypes }, |
| + }; |
| + |
| + char* library_url = |
| + object->cls->internal.as_class.library_url->value.as_string; |
| + char* class_name = |
| + object->cls->internal.as_class.class_name->value.as_string; |
| + if (strcmp("dart:typeddata", library_url) != 0) { |
| + return Dart_CObject::kNumberOfByteArrayTypes; |
| + } |
| + int i = 0; |
| + while (view_class_names[i].name != NULL) { |
| + if (strncmp(view_class_names[i].name, |
| + class_name, |
| + strlen(view_class_names[i].name)) == 0) { |
| + return view_class_names[i].type; |
| + } |
| + i++; |
| + } |
| + return Dart_CObject::kNumberOfByteArrayTypes; |
| +} |
| + |
| + |
| +static int GetByteArrayTypeElementSize(Dart_CObject::ByteArrayType type) { |
| + switch (type) { |
| + case Dart_CObject::kInt8Array: |
| + case Dart_CObject::kUint8Array: |
| + return 1; |
| + case Dart_CObject::kInt16Array: |
| + case Dart_CObject::kUint16Array: |
| + return 2; |
| + default: |
| + break; |
| + } |
| + UNREACHABLE(); |
| + return -1; |
| +} |
| + |
| + |
| Dart_CObject* ApiMessageReader::ReadInlinedObject(intptr_t object_id) { |
| // Read the class header information and lookup the class. |
| intptr_t class_header = ReadIntptrValue(); |
| @@ -217,28 +285,27 @@ Dart_CObject* ApiMessageReader::ReadInlinedObject(intptr_t object_id) { |
| Dart_CObject_Internal::kUninitialized)); |
| // Handle typed data views. |
| - char* library_url = |
| - object->cls->internal.as_class.library_url->value.as_string; |
| - char* class_name = |
| - object->cls->internal.as_class.class_name->value.as_string; |
| - if (strcmp("dart:typeddata", library_url) == 0 && |
| - strncmp("_Uint8ArrayView", class_name, 15) == 0) { |
| + Dart_CObject::ByteArrayType type = GetByteArrayTypeFromView(object); |
| + if (type != Dart_CObject::kNumberOfByteArrayTypes) { |
| object->type = |
| static_cast<Dart_CObject::Type>(Dart_CObject_Internal::kView); |
| - // Skip type arguments. |
| - ReadObjectImpl(); |
| + ReadObjectImpl(); // Skip type arguments. |
| object->internal.as_view.buffer = ReadObjectImpl(); |
| object->internal.as_view.offset_in_bytes = ReadSmiValue(); |
| object->internal.as_view.length = ReadSmiValue(); |
| + ReadObjectImpl(); // Skip last field. |
| // The buffer is fully read now as typed data objects are |
| // serialized in-line. |
| Dart_CObject* buffer = object->internal.as_view.buffer; |
| - ASSERT(buffer->type == Dart_CObject::kUint8Array); |
| + ASSERT(buffer->type == Dart_CObject::kByteArray); |
| // Now turn the view into a byte array. |
| - object->type = Dart_CObject::kUint8Array; |
| - object->value.as_byte_array.length = object->internal.as_view.length; |
| + object->type = Dart_CObject::kByteArray; |
| + object->value.as_byte_array.type = type; |
| + object->value.as_byte_array.length = |
| + object->internal.as_view.length * |
| + GetByteArrayTypeElementSize(type); |
| object->value.as_byte_array.values = |
| buffer->value.as_byte_array.values + |
| object->internal.as_view.offset_in_bytes; |
| @@ -509,19 +576,39 @@ Dart_CObject* ApiMessageReader::ReadInternalVMObject(intptr_t class_id, |
| ::free(utf16); |
| return object; |
| } |
| + |
| +#define READ_TYPED_DATA(type, ctype) \ |
| + { \ |
| + intptr_t len = ReadSmiValue(); \ |
| + Dart_CObject* object = \ |
| + AllocateDartCObjectByteArray(Dart_CObject::k##type##Array, len); \ |
| + AddBackRef(object_id, object, kIsDeserialized); \ |
| + if (len > 0) { \ |
| + ctype* p = \ |
| + reinterpret_cast<ctype*>(object->value.as_byte_array.values); \ |
| + for (intptr_t i = 0; i < len; i++) { \ |
| + p[i] = Read<ctype>(); \ |
| + } \ |
| + } \ |
| + return object; \ |
| + } \ |
| + |
| + case kTypedDataInt8ArrayCid: |
| + case kExternalTypedDataInt8ArrayCid: |
| + READ_TYPED_DATA(Int8, int8_t); |
| + |
| case kTypedDataUint8ArrayCid: |
| - case kExternalTypedDataUint8ArrayCid: { |
| - intptr_t len = ReadSmiValue(); |
| - Dart_CObject* object = AllocateDartCObjectUint8Array(len); |
| - AddBackRef(object_id, object, kIsDeserialized); |
| - if (len > 0) { |
| - uint8_t* p = object->value.as_byte_array.values; |
| - for (intptr_t i = 0; i < len; i++) { |
| - p[i] = Read<uint8_t>(); |
| - } |
| - } |
| - return object; |
| - } |
| + case kExternalTypedDataUint8ArrayCid: |
| + READ_TYPED_DATA(Uint8, uint8_t); |
| + |
| + case kTypedDataInt16ArrayCid: |
| + case kExternalTypedDataInt16ArrayCid: |
| + READ_TYPED_DATA(Int16, int16_t); |
| + |
| + case kTypedDataUint16ArrayCid: |
| + case kExternalTypedDataUint16ArrayCid: |
| + READ_TYPED_DATA(Uint16, uint16_t); |
| + |
| case kGrowableObjectArrayCid: { |
| // A GrowableObjectArray is serialized as its length followed by |
| // its backing store. The backing store is an array with a |
| @@ -924,13 +1011,24 @@ bool ApiMessageWriter::WriteCObjectInlined(Dart_CObject* object, |
| } |
| break; |
| } |
| - case Dart_CObject::kUint8Array: { |
| + case Dart_CObject::kByteArray: { |
| // Write out the serialization header value for this object. |
| WriteInlinedHeader(object); |
| // Write out the class and tags information. |
| - WriteIndexedObject(kTypedDataUint8ArrayCid); |
| - WriteIntptrValue(RawObject::ClassIdTag::update( |
| - kTypedDataUint8ArrayCid, 0)); |
| + intptr_t class_id; |
| + switch (object->value.as_byte_array.type) { |
| + case Dart_CObject::kInt8Array: |
| + class_id = kTypedDataInt8ArrayCid; |
| + break; |
| + case Dart_CObject::kUint8Array: |
| + class_id = kTypedDataUint8ArrayCid; |
| + break; |
| + default: |
| + class_id = kTypedDataUint8ArrayCid; |
|
Mads Ager (google)
2013/04/12 09:03:46
Shouldn't this be an UNIMPLEMENTED instead. The de
Søren Gjesse
2013/04/15 09:14:34
Done.
|
| + } |
| + |
| + WriteIndexedObject(class_id); |
| + WriteIntptrValue(RawObject::ClassIdTag::update(class_id, 0)); |
| uint8_t* bytes = object->value.as_byte_array.values; |
| intptr_t len = object->value.as_byte_array.length; |
| WriteSmi(len); |
| @@ -939,7 +1037,7 @@ bool ApiMessageWriter::WriteCObjectInlined(Dart_CObject* object, |
| } |
| break; |
| } |
| - case Dart_CObject::kExternalUint8Array: { |
| + case Dart_CObject::kExternalByteArray: { |
| // TODO(ager): we are writing C pointers into the message in |
| // order to post external arrays through ports. We need to make |
| // sure that messages containing pointers can never be posted |