| Index: vm/dart_api_message.cc
|
| ===================================================================
|
| --- vm/dart_api_message.cc (revision 8515)
|
| +++ vm/dart_api_message.cc (working copy)
|
| @@ -166,6 +166,17 @@
|
| }
|
|
|
|
|
| +ApiMessageReader::BackRefNode* ApiMessageReader::AllocateBackRefNode(
|
| + Dart_CObject* reference,
|
| + DeserializeState state) {
|
| + BackRefNode* value =
|
| + reinterpret_cast<BackRefNode*>(alloc_(NULL, 0, sizeof(BackRefNode)));
|
| + value->set_reference(reference);
|
| + value->set_state(state);
|
| + 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 +191,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 = GetBackRef(object_id);
|
| + if (value == NULL) {
|
| + value = AllocateDartCObjectArray(len);
|
| + AddBackRef(object_id, value, kIsDeserialized);
|
| + }
|
| + // 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(GetBackRef(object_id) == NULL);
|
| + intptr_t len = ReadSmiValue();
|
| + Dart_CObject* value = AllocateDartCObjectArray(len);
|
| + AddBackRef(object_id, value, kIsNotDeserialized);
|
| + 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 +270,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();
|
| + AddBackRef(object_id, value, kIsDeserialized);
|
| + 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 +284,20 @@
|
| case Object::kTypeParameterClass: {
|
| // TODO(sgjesse): Fix this workaround ignoring the type parameter.
|
| Dart_CObject* value = &dynamic_type_marker;
|
| - AddBackwardReference(object_id, value);
|
| + AddBackRef(object_id, value, kIsDeserialized);
|
| 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 +306,14 @@
|
| } else {
|
| object = AllocateDartCObjectInt64(value);
|
| }
|
| - AddBackwardReference(object_id, object);
|
| + AddBackRef(object_id, object, kIsDeserialized);
|
| 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);
|
| + AddBackRef(object_id, object, kIsDeserialized);
|
| char* p = object->value.as_bigint;
|
| for (intptr_t i = 0; i < len; i++) {
|
| p[i] = Read<uint8_t>();
|
| @@ -259,7 +324,7 @@
|
| case ObjectStore::kDoubleClass: {
|
| // Read the double value for the object.
|
| Dart_CObject* object = AllocateDartCObjectDouble(Read<double>());
|
| - AddBackwardReference(object_id, object);
|
| + AddBackRef(object_id, object, kIsDeserialized);
|
| return object;
|
| }
|
| case ObjectStore::kOneByteStringClass: {
|
| @@ -267,7 +332,7 @@
|
| intptr_t hash = ReadSmiValue();
|
| USE(hash);
|
| Dart_CObject* object = AllocateDartCObjectString(len);
|
| - AddBackwardReference(object_id, object);
|
| + AddBackRef(object_id, object, kIsDeserialized);
|
| char* p = object->value.as_string;
|
| for (intptr_t i = 0; i < len; i++) {
|
| p[i] = Read<uint8_t>();
|
| @@ -284,7 +349,7 @@
|
| case ObjectStore::kUint8ArrayClass: {
|
| intptr_t len = ReadSmiValue();
|
| Dart_CObject* object = AllocateDartCObjectUint8Array(len);
|
| - AddBackwardReference(object_id, object);
|
| + 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++) {
|
| @@ -320,24 +385,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_state(kIsDeserialized);
|
| + }
|
| }
|
| - 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 +413,38 @@
|
| }
|
| }
|
| 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::AddBackRef(intptr_t id,
|
| + Dart_CObject* obj,
|
| + DeserializeState state) {
|
| + intptr_t index = (id - kMaxPredefinedObjectIds);
|
| + ASSERT(index == backward_references_.length());
|
| + BackRefNode* node = AllocateBackRefNode(obj, state);
|
| + ASSERT(node != NULL);
|
| + backward_references_.Add(node);
|
| }
|
|
|
| +
|
| +Dart_CObject* ApiMessageReader::GetBackRef(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);
|
| @@ -423,6 +511,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));
|
| @@ -477,7 +577,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;
|
| @@ -531,20 +696,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);
|
| @@ -566,6 +717,12 @@
|
|
|
| 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.
|
| + // NOTE: The forward list might grow as we process the list.
|
| + for (intptr_t i = 0; i < forward_id_; i++) {
|
| + WriteForwardedCObject(forward_list_[i]);
|
| + }
|
| UnmarkAllCObjects(object);
|
| FinalizeBuffer();
|
| }
|
|
|