Chromium Code Reviews| Index: vm/dart_api_message.cc |
| =================================================================== |
| --- vm/dart_api_message.cc (revision 8411) |
| +++ vm/dart_api_message.cc (working copy) |
| @@ -166,6 +166,18 @@ |
| } |
| +ApiMessageReader::BackwardReferenceNode* |
| +ApiMessageReader::AllocateBackwardReferenceNode( |
| + Dart_CObject* reference, bool is_deserialized) { |
| + BackwardReferenceNode* value = |
| + reinterpret_cast<BackwardReferenceNode*>( |
| + alloc_(NULL, 0, sizeof(BackwardReferenceNode))); |
| + value->set_reference(reference); |
| + value->set_is_deserialized(is_deserialized); |
| + return value; |
| +} |
| + |
| + |
| Dart_CObject* ApiMessageReader::ReadInlinedObject(intptr_t object_id) { |
| // Read the class header information and lookup the class. |
| intptr_t class_header = ReadIntptrValue(); |
| @@ -180,6 +192,77 @@ |
| ASSERT((class_header & kSmiTagMask) != 0); |
| class_id = LookupInternalClass(class_header); |
| + if (class_id == ObjectStore::kArrayClass || |
| + class_id == ObjectStore::kImmutableArrayClass) { |
| + intptr_t len = ReadSmiValue(); |
| + Dart_CObject* value = GetBackwardReference(object_id); |
| + if (value == NULL) { |
| + value = AllocateDartCObjectArray(len); |
| + AddBackwardReference(object_id, value, true); |
| + } |
| + // Skip type arguments. |
| + // TODO(sjesse): Remove this when message serialization format is |
| + // updated (currently type_arguments is leaked). |
| + Dart_CObject* type_arguments = ReadObjectImpl(); |
| + if (type_arguments != &type_arguments_marker && |
| + type_arguments->type != Dart_CObject::kNull) { |
| + return AllocateDartCObjectUnsupported(); |
| + } |
| + for (int i = 0; i < len; i++) { |
| + value->value.as_array.values[i] = ReadObjectRef(); |
| + } |
| + return value; |
| + } |
| + |
| + return ReadInternalVMObject(class_id, object_id); |
| +} |
| + |
| + |
| +Dart_CObject* ApiMessageReader::ReadObjectRef() { |
| + int64_t value = Read<int64_t>(); |
| + if ((value & kSmiTagMask) == 0) { |
| + int64_t untagged_value = value >> kSmiTagShift; |
| + if (kMinInt32 <= untagged_value && untagged_value <= kMaxInt32) { |
| + return AllocateDartCObjectInt32(untagged_value); |
| + } else { |
| + return AllocateDartCObjectInt64(untagged_value); |
| + } |
| + } |
| + ASSERT((value <= kIntptrMax) && (value >= kIntptrMin)); |
| + SerializedHeaderType header_type = SerializedHeaderTag::decode(value); |
| + intptr_t header_value = SerializedHeaderData::decode(value); |
| + |
| + if (header_type == kObjectId) { |
| + return ReadIndexedObject(header_value); |
| + } |
| + ASSERT(header_type == kInlined); |
| + // Read the class header information and lookup the class. |
| + intptr_t class_header = ReadIntptrValue(); |
| + |
| + // Reading of regular dart instances is not supported. |
| + if (SerializedHeaderData::decode(class_header) == kInstanceId) { |
| + return AllocateDartCObjectUnsupported(); |
| + } |
| + ASSERT((class_header & kSmiTagMask) != 0); |
| + intptr_t object_id = header_value; |
| + intptr_t class_id = LookupInternalClass(class_header); |
| + if (class_id == ObjectStore::kArrayClass || |
| + class_id == ObjectStore::kImmutableArrayClass) { |
| + ASSERT(GetBackwardReference(object_id) == NULL); |
| + intptr_t len = ReadSmiValue(); |
| + Dart_CObject* value = AllocateDartCObjectArray(len); |
| + AddBackwardReference(object_id, value, false); |
| + return value; |
| + } |
| + intptr_t tags = ReadIntptrValue(); |
| + USE(tags); |
| + |
| + return ReadInternalVMObject(class_id, object_id); |
| +} |
| + |
| + |
| +Dart_CObject* ApiMessageReader::ReadInternalVMObject(intptr_t class_id, |
| + intptr_t object_id) { |
| switch (class_id) { |
| case Object::kClassClass: { |
| return AllocateDartCObjectUnsupported(); |
| @@ -188,11 +271,11 @@ |
| // TODO(sjesse): Remove this when message serialization format is |
| // updated (currently length is leaked). |
| Dart_CObject* value = &type_arguments_marker; |
| - AddBackwardReference(object_id, value); |
| - Dart_CObject* length = ReadObject(); |
| + AddBackwardReference(object_id, value, true); |
| + Dart_CObject* length = ReadObjectImpl(); |
| ASSERT(length->type == Dart_CObject::kInt32); |
| for (int i = 0; i < length->value.as_int32; i++) { |
| - Dart_CObject* type = ReadObject(); |
| + Dart_CObject* type = ReadObjectImpl(); |
| if (type != &dynamic_type_marker) { |
| return AllocateDartCObjectUnsupported(); |
| } |
| @@ -202,37 +285,20 @@ |
| case Object::kTypeParameterClass: { |
| // TODO(sgjesse): Fix this workaround ignoring the type parameter. |
| Dart_CObject* value = &dynamic_type_marker; |
| - AddBackwardReference(object_id, value); |
| + AddBackwardReference(object_id, value, true); |
| intptr_t index = ReadIntptrValue(); |
| USE(index); |
| intptr_t token_index = ReadIntptrValue(); |
| USE(token_index); |
| int8_t type_state = Read<int8_t>(); |
| USE(type_state); |
| - Dart_CObject* parameterized_class = ReadObject(); |
| + Dart_CObject* parameterized_class = ReadObjectImpl(); |
| // The type parameter is finalized, therefore parameterized_class is null. |
| ASSERT(parameterized_class->type == Dart_CObject::kNull); |
| - Dart_CObject* name = ReadObject(); |
| + Dart_CObject* name = ReadObjectImpl(); |
| ASSERT(name->type == Dart_CObject::kString); |
| return value; |
| } |
| - case ObjectStore::kArrayClass: { |
| - intptr_t len = ReadSmiValue(); |
| - Dart_CObject* value = AllocateDartCObjectArray(len); |
| - AddBackwardReference(object_id, value); |
| - // Skip type arguments. |
| - // TODO(sjesse): Remove this when message serialization format is |
| - // updated (currently type_arguments is leaked). |
| - Dart_CObject* type_arguments = ReadObject(); |
| - if (type_arguments != &type_arguments_marker && |
| - type_arguments->type != Dart_CObject::kNull) { |
| - return AllocateDartCObjectUnsupported(); |
| - } |
| - for (int i = 0; i < len; i++) { |
| - value->value.as_array.values[i] = ReadObject(); |
| - } |
| - return value; |
| - } |
| case ObjectStore::kMintClass: { |
| int64_t value = Read<int64_t>(); |
| Dart_CObject* object; |
| @@ -241,14 +307,14 @@ |
| } else { |
| object = AllocateDartCObjectInt64(value); |
| } |
| - AddBackwardReference(object_id, object); |
| + AddBackwardReference(object_id, object, true); |
| return object; |
| } |
| case ObjectStore::kBigintClass: { |
| // Read in the hex string representation of the bigint. |
| intptr_t len = ReadIntptrValue(); |
| Dart_CObject* object = AllocateDartCObjectBigint(len); |
| - AddBackwardReference(object_id, object); |
| + AddBackwardReference(object_id, object, true); |
| char* p = object->value.as_bigint; |
| for (intptr_t i = 0; i < len; i++) { |
| p[i] = Read<uint8_t>(); |
| @@ -259,7 +325,7 @@ |
| case ObjectStore::kDoubleClass: { |
| // Read the double value for the object. |
| Dart_CObject* object = AllocateDartCObjectDouble(Read<double>()); |
| - AddBackwardReference(object_id, object); |
| + AddBackwardReference(object_id, object, true); |
| return object; |
| } |
| case ObjectStore::kOneByteStringClass: { |
| @@ -267,7 +333,7 @@ |
| intptr_t hash = ReadSmiValue(); |
| USE(hash); |
| Dart_CObject* object = AllocateDartCObjectString(len); |
| - AddBackwardReference(object_id, object); |
| + AddBackwardReference(object_id, object, true); |
| char* p = object->value.as_string; |
| for (intptr_t i = 0; i < len; i++) { |
| p[i] = Read<uint8_t>(); |
| @@ -284,7 +350,7 @@ |
| case ObjectStore::kUint8ArrayClass: { |
| intptr_t len = ReadSmiValue(); |
| Dart_CObject* object = AllocateDartCObjectUint8Array(len); |
| - AddBackwardReference(object_id, object); |
| + AddBackwardReference(object_id, object, true); |
| if (len > 0) { |
| uint8_t* p = object->value.as_byte_array.values; |
| for (intptr_t i = 0; i < len; i++) { |
| @@ -320,24 +386,24 @@ |
| } |
| intptr_t index = object_id - kMaxPredefinedObjectIds; |
| ASSERT((0 <= index) && (index < backward_references_.length())); |
| - ASSERT(backward_references_[index] != NULL); |
| - return backward_references_[index]; |
| + ASSERT(backward_references_[index]->reference() != NULL); |
| + return backward_references_[index]->reference(); |
| } |
| -Dart_CObject* ApiMessageReader::ReadObjectImpl(intptr_t header) { |
| - SerializedHeaderType header_type = SerializedHeaderTag::decode(header); |
| - intptr_t header_value = SerializedHeaderData::decode(header); |
| - |
| - if (header_type == kObjectId) { |
| - return ReadIndexedObject(header_value); |
| +Dart_CObject* ApiMessageReader::ReadObject() { |
| + Dart_CObject* value = ReadObjectImpl(); |
| + for (intptr_t i = 0; i < backward_references_.length(); i++) { |
| + if (!backward_references_[i]->is_deserialized()) { |
| + ReadObjectImpl(); |
| + backward_references_[i]->set_is_deserialized(true); |
| + } |
| } |
| - ASSERT(header_type == kInlined); |
| - return ReadInlinedObject(header_value); |
| + return value; |
| } |
| -Dart_CObject* ApiMessageReader::ReadObject() { |
| +Dart_CObject* ApiMessageReader::ReadObjectImpl() { |
| int64_t value = Read<int64_t>(); |
| if ((value & kSmiTagMask) == 0) { |
| int64_t untagged_value = value >> kSmiTagShift; |
| @@ -348,15 +414,39 @@ |
| } |
| } |
| ASSERT((value <= kIntptrMax) && (value >= kIntptrMin)); |
| - return ReadObjectImpl(value); |
| + SerializedHeaderType header_type = SerializedHeaderTag::decode(value); |
| + intptr_t header_value = SerializedHeaderData::decode(value); |
| + |
| + if (header_type == kObjectId) { |
| + return ReadIndexedObject(header_value); |
| + } |
| + ASSERT(header_type == kInlined); |
| + return ReadInlinedObject(header_value); |
| } |
| -void ApiMessageReader::AddBackwardReference(intptr_t id, Dart_CObject* obj) { |
| - ASSERT((id - kMaxPredefinedObjectIds) == backward_references_.length()); |
| - backward_references_.Add(obj); |
| +void ApiMessageReader::AddBackwardReference(intptr_t id, |
| + Dart_CObject* obj, |
| + bool is_deserialized) { |
| + intptr_t index = (id - kMaxPredefinedObjectIds); |
| + ASSERT(index == backward_references_.length()); |
| + BackwardReferenceNode* node = AllocateBackwardReferenceNode(obj, |
| + is_deserialized); |
| + ASSERT(node != NULL); |
| + backward_references_.Add(node); |
| } |
| + |
| +Dart_CObject* ApiMessageReader::GetBackwardReference(intptr_t id) { |
| + ASSERT(id >= kMaxPredefinedObjectIds); |
| + intptr_t index = (id - kMaxPredefinedObjectIds); |
| + if (index < backward_references_.length()) { |
| + return backward_references_[index]->reference(); |
| + } |
| + return NULL; |
| +} |
| + |
| + |
| void ApiMessageWriter::WriteMessage(intptr_t field_count, intptr_t *data) { |
| // Write out the serialization header value for this object. |
| WriteSerializationMarker(kInlined, kMaxPredefinedObjectIds); |
| @@ -404,7 +494,8 @@ |
| intptr_t ApiMessageWriter::GetMarkedCObjectMark(Dart_CObject* object) { |
| ASSERT(IsCObjectMarked(object)); |
| - intptr_t mark_value = ((object->type & kDartCObjectMarkMask) >> 3); |
| + intptr_t mark_value = |
| + ((object->type & kDartCObjectMarkMask) >> kDartCObjectTypeBits); |
| // An offset was added to object id for making marking object id 0 possible. |
| return mark_value - kDartCObjectMarkOffset; |
| } |
| @@ -422,6 +513,18 @@ |
| } |
| +void ApiMessageWriter::AddToForwardList(Dart_CObject* object) { |
| + if (forward_id_ >= forward_list_length_) { |
| + intptr_t new_size = (forward_list_length_ * sizeof(object)) * 2; |
| + void* new_list = ::realloc(forward_list_, new_size); |
| + ASSERT(new_list != NULL); |
| + forward_list_ = reinterpret_cast<Dart_CObject**>(new_list); |
| + } |
| + forward_list_[forward_id_] = object; |
| + forward_id_ += 1; |
| +} |
| + |
| + |
| void ApiMessageWriter::WriteSmi(int64_t value) { |
| ASSERT(Smi::IsValid64(value)); |
| Write<RawObject*>(Smi::New(value)); |
| @@ -476,7 +579,72 @@ |
| return; |
| } |
| - switch (object->type) { |
| + Dart_CObject::Type type = object->type; |
| + if (type == Dart_CObject::kArray) { |
| + // Write out the serialization header value for this object. |
| + WriteInlinedHeader(object); |
| + // Write out the class and tags information. |
| + WriteObjectHeader(ObjectStore::kArrayClass, 0); |
| + WriteSmi(object->value.as_array.length); |
| + // Write out the type arguments. |
| + WriteIndexedObject(Object::kNullObject); |
| + // Write out array elements. |
| + for (int i = 0; i < object->value.as_array.length; i++) { |
| + WriteCObjectRef(object->value.as_array.values[i]); |
| + } |
| + return; |
| + } |
| + return WriteCObjectInlined(object, type); |
| +} |
| + |
| + |
| +void ApiMessageWriter::WriteCObjectRef(Dart_CObject* object) { |
| + if (IsCObjectMarked(object)) { |
| + intptr_t object_id = GetMarkedCObjectMark(object); |
| + WriteIndexedObject(kMaxPredefinedObjectIds + object_id); |
| + return; |
| + } |
| + |
| + Dart_CObject::Type type = object->type; |
| + if (type == Dart_CObject::kArray) { |
| + // Write out the serialization header value for this object. |
| + WriteInlinedHeader(object); |
| + // Write out the class information. |
| + WriteIndexedObject(ObjectStore::kArrayClass); |
| + // Write out the length information. |
| + WriteSmi(object->value.as_array.length); |
| + // Add object to forward list so that this object is serialized later. |
| + AddToForwardList(object); |
| + return; |
| + } |
| + return WriteCObjectInlined(object, type); |
| +} |
| + |
| + |
| +void ApiMessageWriter::WriteForwardedCObject(Dart_CObject* object) { |
| + ASSERT(IsCObjectMarked(object)); |
| + Dart_CObject::Type type = |
| + static_cast<Dart_CObject::Type>(object->type & kDartCObjectTypeMask); |
| + ASSERT(type == Dart_CObject::kArray); |
| + |
| + // Write out the serialization header value for this object. |
| + intptr_t object_id = GetMarkedCObjectMark(object); |
| + WriteSerializationMarker(kInlined, kMaxPredefinedObjectIds + object_id); |
| + // Write out the class and tags information. |
| + WriteObjectHeader(ObjectStore::kArrayClass, 0); |
| + WriteSmi(object->value.as_array.length); |
| + // Write out the type arguments. |
| + WriteIndexedObject(Object::kNullObject); |
| + // Write out array elements. |
| + for (int i = 0; i < object->value.as_array.length; i++) { |
| + WriteCObjectRef(object->value.as_array.values[i]); |
| + } |
| +} |
| + |
| + |
| +void ApiMessageWriter::WriteCObjectInlined(Dart_CObject* object, |
| + Dart_CObject::Type type) { |
| + switch (type) { |
| case Dart_CObject::kNull: |
| WriteIndexedObject(Object::kNullObject); |
| break; |
| @@ -530,20 +698,6 @@ |
| } |
| break; |
| } |
| - case Dart_CObject::kArray: { |
| - // Write out the serialization header value for this object. |
| - WriteInlinedHeader(object); |
| - // Write out the class and tags information. |
| - WriteObjectHeader(ObjectStore::kArrayClass, 0); |
| - WriteSmi(object->value.as_array.length); |
| - // Write out the type arguments. |
| - WriteIndexedObject(Object::kNullObject); |
| - // Write out array elements. |
| - for (int i = 0; i < object->value.as_array.length; i++) { |
| - WriteCObject(object->value.as_array.values[i]); |
| - } |
| - break; |
| - } |
| case Dart_CObject::kUint8Array: { |
| // Write out the serialization header value for this object. |
| WriteInlinedHeader(object); |
| @@ -565,6 +719,11 @@ |
| void ApiMessageWriter::WriteCMessage(Dart_CObject* object) { |
| WriteCObject(object); |
| + // Write out all objects that were added to the forward list and have |
| + // not been serialized yet. These would typically be fields of arrays. |
|
Søren Gjesse
2012/06/08 08:12:12
Maybe extend comment here to mention that the forw
siva
2012/06/11 20:49:06
Done.
|
| + for (intptr_t i = 0; i < forward_id_; i++) { |
| + WriteForwardedCObject(forward_list_[i]); |
| + } |
| UnmarkAllCObjects(object); |
| FinalizeBuffer(); |
| } |