mirror of
https://github.com/dart-lang/sdk
synced 2024-11-05 18:22:09 +00:00
1. Remove recursion during snapshot writing and reading
2. set thread stack size to 128k 3. Fix the native message handler to ensure that it works with the new model of not recursively inlining objects. Review URL: https://chromiumcodereview.appspot.com//10535066 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8517 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
parent
e042b19b96
commit
c078663643
7 changed files with 823 additions and 297 deletions
|
@ -87,7 +87,7 @@ int Thread::Start(ThreadStartFunction function, uword parameter) {
|
|||
result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
RETURN_ON_PTHREAD_FAILURE(result);
|
||||
|
||||
result = pthread_attr_setstacksize(&attr, 1024 * KB);
|
||||
result = pthread_attr_setstacksize(&attr, 64 * KB);
|
||||
RETURN_ON_PTHREAD_FAILURE(result);
|
||||
|
||||
ThreadStartData* data = new ThreadStartData(function, parameter);
|
||||
|
|
|
@ -71,11 +71,7 @@ int Thread::Start(ThreadStartFunction function, uword parameter) {
|
|||
result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
RETURN_ON_PTHREAD_FAILURE(result);
|
||||
|
||||
#ifdef DEBUG
|
||||
const int kStackSize = (512 * KB);
|
||||
#else
|
||||
const int kStackSize = (128 * KB);
|
||||
#endif
|
||||
const int kStackSize = (64 * KB);
|
||||
result = pthread_attr_setstacksize(&attr, kStackSize);
|
||||
RETURN_ON_PTHREAD_FAILURE(result);
|
||||
|
||||
|
|
|
@ -166,6 +166,17 @@ Dart_CObject* ApiMessageReader::AllocateDartCObjectArray(intptr_t length) {
|
|||
}
|
||||
|
||||
|
||||
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 @@ Dart_CObject* ApiMessageReader::ReadInlinedObject(intptr_t object_id) {
|
|||
|
||||
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 @@ Dart_CObject* ApiMessageReader::ReadInlinedObject(intptr_t object_id) {
|
|||
// 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 @@ Dart_CObject* ApiMessageReader::ReadInlinedObject(intptr_t object_id) {
|
|||
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 @@ Dart_CObject* ApiMessageReader::ReadInlinedObject(intptr_t object_id) {
|
|||
} 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 @@ Dart_CObject* ApiMessageReader::ReadInlinedObject(intptr_t object_id) {
|
|||
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 @@ Dart_CObject* ApiMessageReader::ReadInlinedObject(intptr_t object_id) {
|
|||
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 @@ Dart_CObject* ApiMessageReader::ReadInlinedObject(intptr_t object_id) {
|
|||
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 @@ Dart_CObject* ApiMessageReader::ReadIndexedObject(intptr_t object_id) {
|
|||
}
|
||||
intptr_t index = object_id - kMaxPredefinedObjectIds;
|
||||
ASSERT((0 <= index) && (index < backward_references_.length()));
|
||||
ASSERT(backward_references_[index] != NULL);
|
||||
return backward_references_[index];
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
ASSERT(header_type == kInlined);
|
||||
return ReadInlinedObject(header_value);
|
||||
ASSERT(backward_references_[index]->reference() != NULL);
|
||||
return backward_references_[index]->reference();
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
Dart_CObject* ApiMessageReader::ReadObjectImpl() {
|
||||
int64_t value = Read<int64_t>();
|
||||
if ((value & kSmiTagMask) == 0) {
|
||||
int64_t untagged_value = value >> kSmiTagShift;
|
||||
|
@ -348,15 +413,38 @@ Dart_CObject* ApiMessageReader::ReadObject() {
|
|||
}
|
||||
}
|
||||
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::UnmarkAllCObjects(Dart_CObject* object) {
|
|||
}
|
||||
|
||||
|
||||
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 @@ void ApiMessageWriter::WriteCObject(Dart_CObject* object) {
|
|||
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 @@ void ApiMessageWriter::WriteCObject(Dart_CObject* object) {
|
|||
}
|
||||
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::WriteCObject(Dart_CObject* object) {
|
|||
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -33,6 +33,22 @@ class ApiMessageReader : public BaseReader {
|
|||
Dart_CObject* ReadMessage();
|
||||
|
||||
private:
|
||||
class BackRefNode {
|
||||
public:
|
||||
BackRefNode(Dart_CObject* reference, DeserializeState state)
|
||||
: reference_(reference), state_(state) {}
|
||||
Dart_CObject* reference() const { return reference_; }
|
||||
void set_reference(Dart_CObject* reference) { reference_ = reference; }
|
||||
bool is_deserialized() const { return state_ == kIsDeserialized; }
|
||||
void set_state(DeserializeState value) { state_ = value; }
|
||||
|
||||
private:
|
||||
Dart_CObject* reference_;
|
||||
DeserializeState state_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(BackRefNode);
|
||||
};
|
||||
|
||||
// Allocates a Dart_CObject object.
|
||||
Dart_CObject* AllocateDartCObject();
|
||||
// Allocates a Dart_CObject object with the specified type.
|
||||
|
@ -58,17 +74,24 @@ class ApiMessageReader : public BaseReader {
|
|||
Dart_CObject* AllocateDartCObjectUint8Array(intptr_t length);
|
||||
// Allocates a C array of Dart_CObject objects.
|
||||
Dart_CObject* AllocateDartCObjectArray(intptr_t length);
|
||||
// Allocates a backwards reference node.
|
||||
BackRefNode* AllocateBackRefNode(Dart_CObject* ref, DeserializeState state);
|
||||
|
||||
void Init();
|
||||
|
||||
intptr_t LookupInternalClass(intptr_t class_header);
|
||||
Dart_CObject* ReadInternalVMObject(intptr_t class_id, intptr_t object_id);
|
||||
Dart_CObject* ReadInlinedObject(intptr_t object_id);
|
||||
Dart_CObject* ReadObjectImpl(intptr_t header);
|
||||
Dart_CObject* ReadObjectImpl();
|
||||
Dart_CObject* ReadIndexedObject(intptr_t object_id);
|
||||
Dart_CObject* ReadObjectRef();
|
||||
Dart_CObject* ReadObject();
|
||||
|
||||
// Add object to backward references.
|
||||
void AddBackwardReference(intptr_t id, Dart_CObject* obj);
|
||||
void AddBackRef(intptr_t id, Dart_CObject* obj, DeserializeState state);
|
||||
|
||||
// Get an object from the backward references list.
|
||||
Dart_CObject* GetBackRef(intptr_t id);
|
||||
|
||||
Dart_CObject_Internal* AsInternal(Dart_CObject* object) {
|
||||
ASSERT(object->type >= Dart_CObject::kNumberOfTypes);
|
||||
|
@ -79,7 +102,7 @@ class ApiMessageReader : public BaseReader {
|
|||
// either in the supplied zone or using the supplied allocation
|
||||
// function.
|
||||
ReAlloc alloc_;
|
||||
ApiGrowableArray<Dart_CObject*> backward_references_;
|
||||
ApiGrowableArray<BackRefNode*> backward_references_;
|
||||
|
||||
Dart_CObject type_arguments_marker;
|
||||
Dart_CObject dynamic_type_marker;
|
||||
|
@ -89,10 +112,13 @@ class ApiMessageReader : public BaseReader {
|
|||
class ApiMessageWriter : public BaseWriter {
|
||||
public:
|
||||
ApiMessageWriter(uint8_t** buffer, ReAlloc alloc)
|
||||
: BaseWriter(buffer, alloc), object_id_(0) {
|
||||
: BaseWriter(buffer, alloc), object_id_(0),
|
||||
forward_list_(NULL), forward_list_length_(0), forward_id_(0) {
|
||||
ASSERT(kDartCObjectTypeMask >= Dart_CObject::kNumberOfTypes - 1);
|
||||
}
|
||||
~ApiMessageWriter() { }
|
||||
~ApiMessageWriter() {
|
||||
delete forward_list_;
|
||||
}
|
||||
|
||||
// Writes a message of integers.
|
||||
void WriteMessage(intptr_t field_count, intptr_t *data);
|
||||
|
@ -114,6 +140,7 @@ class ApiMessageWriter : public BaseWriter {
|
|||
bool IsCObjectMarked(Dart_CObject* object);
|
||||
intptr_t GetMarkedCObjectMark(Dart_CObject* object);
|
||||
void UnmarkAllCObjects(Dart_CObject* object);
|
||||
void AddToForwardList(Dart_CObject* object);
|
||||
|
||||
void WriteSmi(int64_t value);
|
||||
void WriteMint(Dart_CObject* object, int64_t value);
|
||||
|
@ -121,8 +148,14 @@ class ApiMessageWriter : public BaseWriter {
|
|||
void WriteInt64(Dart_CObject* object);
|
||||
void WriteInlinedHeader(Dart_CObject* object);
|
||||
void WriteCObject(Dart_CObject* object);
|
||||
void WriteCObjectRef(Dart_CObject* object);
|
||||
void WriteForwardedCObject(Dart_CObject* object);
|
||||
void WriteCObjectInlined(Dart_CObject* object, Dart_CObject::Type type);
|
||||
|
||||
intptr_t object_id_;
|
||||
Dart_CObject** forward_list_;
|
||||
intptr_t forward_list_length_;
|
||||
intptr_t forward_id_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ApiMessageWriter);
|
||||
};
|
||||
|
|
|
@ -41,7 +41,7 @@ RawClass* Class::ReadFrom(SnapshotReader* reader,
|
|||
} else {
|
||||
cls = Class::GetClass(object_kind);
|
||||
}
|
||||
reader->AddBackwardReference(object_id, &cls);
|
||||
reader->AddBackRef(object_id, &cls, kIsDeserialized);
|
||||
|
||||
// Set the object tags.
|
||||
cls.set_tags(tags);
|
||||
|
@ -65,7 +65,7 @@ RawClass* Class::ReadFrom(SnapshotReader* reader,
|
|||
// allocations may happen.
|
||||
intptr_t num_flds = (cls.raw()->to() - cls.raw()->from());
|
||||
for (intptr_t i = 0; i <= num_flds; i++) {
|
||||
*(cls.raw()->from() + i) = reader->ReadObject();
|
||||
*(cls.raw()->from() + i) = reader->ReadObjectRef();
|
||||
}
|
||||
} else {
|
||||
cls ^= reader->ReadClassId(object_id);
|
||||
|
@ -118,7 +118,7 @@ RawUnresolvedClass* UnresolvedClass::ReadFrom(SnapshotReader* reader,
|
|||
// Allocate parameterized type object.
|
||||
UnresolvedClass& unresolved_class = UnresolvedClass::ZoneHandle(
|
||||
reader->isolate(), NEW_OBJECT(UnresolvedClass));
|
||||
reader->AddBackwardReference(object_id, &unresolved_class);
|
||||
reader->AddBackRef(object_id, &unresolved_class, kIsDeserialized);
|
||||
|
||||
// Set the object tags.
|
||||
unresolved_class.set_tags(tags);
|
||||
|
@ -132,7 +132,7 @@ RawUnresolvedClass* UnresolvedClass::ReadFrom(SnapshotReader* reader,
|
|||
intptr_t num_flds = (unresolved_class.raw()->to() -
|
||||
unresolved_class.raw()->from());
|
||||
for (intptr_t i = 0; i <= num_flds; i++) {
|
||||
*(unresolved_class.raw()->from() + i) = reader->ReadObject();
|
||||
*(unresolved_class.raw()->from() + i) = reader->ReadObjectRef();
|
||||
}
|
||||
return unresolved_class.raw();
|
||||
}
|
||||
|
@ -184,7 +184,7 @@ RawType* Type::ReadFrom(SnapshotReader* reader,
|
|||
// Allocate parameterized type object.
|
||||
Type& parameterized_type = Type::ZoneHandle(
|
||||
reader->isolate(), NEW_OBJECT(Type));
|
||||
reader->AddBackwardReference(object_id, ¶meterized_type);
|
||||
reader->AddBackRef(object_id, ¶meterized_type, kIsDeserialized);
|
||||
|
||||
// Set the object tags.
|
||||
parameterized_type.set_tags(tags);
|
||||
|
@ -199,7 +199,7 @@ RawType* Type::ReadFrom(SnapshotReader* reader,
|
|||
intptr_t num_flds = (parameterized_type.raw()->to() -
|
||||
parameterized_type.raw()->from());
|
||||
for (intptr_t i = 0; i <= num_flds; i++) {
|
||||
*(parameterized_type.raw()->from() + i) = reader->ReadObject();
|
||||
*(parameterized_type.raw()->from() + i) = reader->ReadObjectImpl();
|
||||
}
|
||||
|
||||
// If object needs to be a canonical object, Canonicalize it.
|
||||
|
@ -226,7 +226,7 @@ void RawType::WriteTo(SnapshotWriter* writer,
|
|||
writer->Write<int8_t>(ptr()->type_state_);
|
||||
|
||||
// Write out all the object pointer fields.
|
||||
SnapshotWriterVisitor visitor(writer);
|
||||
SnapshotWriterVisitor visitor(writer, false);
|
||||
visitor.VisitPointers(from(), to());
|
||||
}
|
||||
|
||||
|
@ -240,7 +240,7 @@ RawTypeParameter* TypeParameter::ReadFrom(SnapshotReader* reader,
|
|||
// Allocate type parameter object.
|
||||
TypeParameter& type_parameter = TypeParameter::ZoneHandle(
|
||||
reader->isolate(), NEW_OBJECT(TypeParameter));
|
||||
reader->AddBackwardReference(object_id, &type_parameter);
|
||||
reader->AddBackRef(object_id, &type_parameter, kIsDeserialized);
|
||||
|
||||
// Set the object tags.
|
||||
type_parameter.set_tags(tags);
|
||||
|
@ -256,7 +256,7 @@ RawTypeParameter* TypeParameter::ReadFrom(SnapshotReader* reader,
|
|||
intptr_t num_flds = (type_parameter.raw()->to() -
|
||||
type_parameter.raw()->from());
|
||||
for (intptr_t i = 0; i <= num_flds; i++) {
|
||||
*(type_parameter.raw()->from() + i) = reader->ReadObject();
|
||||
*(type_parameter.raw()->from() + i) = reader->ReadObjectImpl();
|
||||
}
|
||||
|
||||
return type_parameter.raw();
|
||||
|
@ -281,7 +281,7 @@ void RawTypeParameter::WriteTo(SnapshotWriter* writer,
|
|||
writer->Write<int8_t>(ptr()->type_state_);
|
||||
|
||||
// Write out all the object pointer fields.
|
||||
SnapshotWriterVisitor visitor(writer);
|
||||
SnapshotWriterVisitor visitor(writer, false);
|
||||
visitor.VisitPointers(from(), to());
|
||||
}
|
||||
|
||||
|
@ -314,11 +314,11 @@ RawTypeArguments* TypeArguments::ReadFrom(SnapshotReader* reader,
|
|||
|
||||
TypeArguments& type_arguments = TypeArguments::ZoneHandle(
|
||||
reader->isolate(), NEW_OBJECT_WITH_LEN(TypeArguments, len));
|
||||
reader->AddBackwardReference(object_id, &type_arguments);
|
||||
reader->AddBackRef(object_id, &type_arguments, kIsDeserialized);
|
||||
|
||||
// Now set all the object fields.
|
||||
for (intptr_t i = 0; i < len; i++) {
|
||||
*reader->TypeHandle() ^= reader->ReadObject();
|
||||
*reader->TypeHandle() ^= reader->ReadObjectImpl();
|
||||
type_arguments.SetTypeAt(i, *reader->TypeHandle());
|
||||
}
|
||||
|
||||
|
@ -353,7 +353,7 @@ void RawTypeArguments::WriteTo(SnapshotWriter* writer,
|
|||
// Write out the individual types.
|
||||
intptr_t len = Smi::Value(ptr()->length_);
|
||||
for (intptr_t i = 0; i < len; i++) {
|
||||
writer->WriteObject(ptr()->types_[i]);
|
||||
writer->WriteObjectImpl(ptr()->types_[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -370,7 +370,7 @@ RawInstantiatedTypeArguments* InstantiatedTypeArguments::ReadFrom(
|
|||
InstantiatedTypeArguments& instantiated_type_arguments =
|
||||
InstantiatedTypeArguments::ZoneHandle(reader->isolate(),
|
||||
InstantiatedTypeArguments::New());
|
||||
reader->AddBackwardReference(object_id, &instantiated_type_arguments);
|
||||
reader->AddBackRef(object_id, &instantiated_type_arguments, kIsDeserialized);
|
||||
|
||||
// Set the object tags.
|
||||
instantiated_type_arguments.set_tags(tags);
|
||||
|
@ -381,7 +381,7 @@ RawInstantiatedTypeArguments* InstantiatedTypeArguments::ReadFrom(
|
|||
intptr_t num_flds = (instantiated_type_arguments.raw()->to() -
|
||||
instantiated_type_arguments.raw()->from());
|
||||
for (intptr_t i = 0; i <= num_flds; i++) {
|
||||
*(instantiated_type_arguments.raw()->from() + i) = reader->ReadObject();
|
||||
*(instantiated_type_arguments.raw()->from() + i) = reader->ReadObjectImpl();
|
||||
}
|
||||
return instantiated_type_arguments.raw();
|
||||
}
|
||||
|
@ -401,7 +401,7 @@ void RawInstantiatedTypeArguments::WriteTo(SnapshotWriter* writer,
|
|||
writer->GetObjectTags(this));
|
||||
|
||||
// Write out all the object pointer fields.
|
||||
SnapshotWriterVisitor visitor(writer);
|
||||
SnapshotWriterVisitor visitor(writer, false);
|
||||
visitor.VisitPointers(from(), to());
|
||||
}
|
||||
|
||||
|
@ -416,7 +416,7 @@ RawFunction* Function::ReadFrom(SnapshotReader* reader,
|
|||
// Allocate function object.
|
||||
Function& func = Function::ZoneHandle(
|
||||
reader->isolate(), NEW_OBJECT(Function));
|
||||
reader->AddBackwardReference(object_id, &func);
|
||||
reader->AddBackRef(object_id, &func, kIsDeserialized);
|
||||
|
||||
// Set the object tags.
|
||||
func.set_tags(tags);
|
||||
|
@ -438,7 +438,7 @@ RawFunction* Function::ReadFrom(SnapshotReader* reader,
|
|||
// allocations may happen.
|
||||
intptr_t num_flds = (func.raw()->to() - func.raw()->from());
|
||||
for (intptr_t i = 0; i <= num_flds; i++) {
|
||||
*(func.raw()->from() + i) = reader->ReadObject();
|
||||
*(func.raw()->from() + i) = reader->ReadObjectRef();
|
||||
}
|
||||
|
||||
return func.raw();
|
||||
|
@ -486,7 +486,7 @@ RawField* Field::ReadFrom(SnapshotReader* reader,
|
|||
|
||||
// Allocate field object.
|
||||
Field& field = Field::ZoneHandle(reader->isolate(), NEW_OBJECT(Field));
|
||||
reader->AddBackwardReference(object_id, &field);
|
||||
reader->AddBackRef(object_id, &field, kIsDeserialized);
|
||||
|
||||
// Set the object tags.
|
||||
field.set_tags(tags);
|
||||
|
@ -502,7 +502,7 @@ RawField* Field::ReadFrom(SnapshotReader* reader,
|
|||
// allocations may happen.
|
||||
intptr_t num_flds = (field.raw()->to() - field.raw()->from());
|
||||
for (intptr_t i = 0; i <= num_flds; i++) {
|
||||
*(field.raw()->from() + i) = reader->ReadObject();
|
||||
*(field.raw()->from() + i) = reader->ReadObjectRef();
|
||||
}
|
||||
|
||||
return field.raw();
|
||||
|
@ -544,7 +544,7 @@ RawLiteralToken* LiteralToken::ReadFrom(SnapshotReader* reader,
|
|||
// Create the literal token object.
|
||||
LiteralToken& literal_token = LiteralToken::ZoneHandle(
|
||||
reader->isolate(), NEW_OBJECT(LiteralToken));
|
||||
reader->AddBackwardReference(object_id, &literal_token);
|
||||
reader->AddBackRef(object_id, &literal_token, kIsDeserialized);
|
||||
|
||||
// Set the object tags.
|
||||
literal_token.set_tags(tags);
|
||||
|
@ -552,9 +552,9 @@ RawLiteralToken* LiteralToken::ReadFrom(SnapshotReader* reader,
|
|||
// Read the token attributes.
|
||||
Token::Kind token_kind = static_cast<Token::Kind>(reader->ReadIntptrValue());
|
||||
literal_token.set_kind(token_kind);
|
||||
*reader->StringHandle() ^= reader->ReadObject();
|
||||
*reader->StringHandle() ^= reader->ReadObjectImpl();
|
||||
literal_token.set_literal(*reader->StringHandle());
|
||||
*reader->ObjectHandle() = reader->ReadObject();
|
||||
*reader->ObjectHandle() = reader->ReadObjectImpl();
|
||||
literal_token.set_value(*reader->ObjectHandle());
|
||||
|
||||
return literal_token.raw();
|
||||
|
@ -578,8 +578,8 @@ void RawLiteralToken::WriteTo(SnapshotWriter* writer,
|
|||
writer->Write<intptr_t>(ptr()->kind_);
|
||||
|
||||
// Write out literal and value fields.
|
||||
writer->WriteObject(ptr()->literal_);
|
||||
writer->WriteObject(ptr()->value_);
|
||||
writer->WriteObjectImpl(ptr()->literal_);
|
||||
writer->WriteObjectImpl(ptr()->value_);
|
||||
}
|
||||
|
||||
|
||||
|
@ -596,14 +596,14 @@ RawTokenStream* TokenStream::ReadFrom(SnapshotReader* reader,
|
|||
// Create the token stream object.
|
||||
TokenStream& token_stream = TokenStream::ZoneHandle(
|
||||
reader->isolate(), NEW_OBJECT_WITH_LEN(TokenStream, len));
|
||||
reader->AddBackwardReference(object_id, &token_stream);
|
||||
reader->AddBackRef(object_id, &token_stream, kIsDeserialized);
|
||||
|
||||
// Set the object tags.
|
||||
token_stream.set_tags(tags);
|
||||
|
||||
// Read the token stream into the TokenStream.
|
||||
for (intptr_t i = 0; i < len; i++) {
|
||||
*reader->ObjectHandle() = reader->ReadObject();
|
||||
*reader->ObjectHandle() = reader->ReadObjectImpl();
|
||||
token_stream.SetTokenAt(i, *reader->ObjectHandle());
|
||||
}
|
||||
return token_stream.raw();
|
||||
|
@ -630,7 +630,7 @@ void RawTokenStream::WriteTo(SnapshotWriter* writer,
|
|||
// Write out the token stream (token kind and literal).
|
||||
intptr_t len = Smi::Value(ptr()->length_);
|
||||
for (intptr_t i = 0; i < TokenStream::StreamLength(len); i++) {
|
||||
writer->WriteObject(ptr()->data_[i]);
|
||||
writer->WriteObjectImpl(ptr()->data_[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -644,7 +644,7 @@ RawScript* Script::ReadFrom(SnapshotReader* reader,
|
|||
|
||||
// Allocate script object.
|
||||
Script& script = Script::ZoneHandle(reader->isolate(), NEW_OBJECT(Script));
|
||||
reader->AddBackwardReference(object_id, &script);
|
||||
reader->AddBackRef(object_id, &script, kIsDeserialized);
|
||||
|
||||
// Set the object tags.
|
||||
script.set_tags(tags);
|
||||
|
@ -652,12 +652,12 @@ RawScript* Script::ReadFrom(SnapshotReader* reader,
|
|||
// Set all the object fields.
|
||||
// TODO(5411462): Need to assert No GC can happen here, even though
|
||||
// allocations may happen.
|
||||
*reader->StringHandle() ^= reader->ReadObject();
|
||||
*reader->StringHandle() ^= reader->ReadObjectImpl();
|
||||
script.set_url(*reader->StringHandle());
|
||||
*reader->StringHandle() ^= String::null();
|
||||
script.set_source(*reader->StringHandle());
|
||||
TokenStream& stream = TokenStream::Handle();
|
||||
stream ^= reader->ReadObject();
|
||||
stream ^= reader->ReadObjectImpl();
|
||||
script.set_tokens(stream);
|
||||
|
||||
return script.raw();
|
||||
|
@ -679,8 +679,8 @@ void RawScript::WriteTo(SnapshotWriter* writer,
|
|||
writer->WriteObjectHeader(Object::kScriptClass, writer->GetObjectTags(this));
|
||||
|
||||
// Write out all the object pointer fields.
|
||||
writer->WriteObject(ptr()->url_);
|
||||
writer->WriteObject(ptr()->tokens_);
|
||||
writer->WriteObjectImpl(ptr()->url_);
|
||||
writer->WriteObjectImpl(ptr()->tokens_);
|
||||
}
|
||||
|
||||
|
||||
|
@ -692,12 +692,12 @@ RawLibrary* Library::ReadFrom(SnapshotReader* reader,
|
|||
ASSERT(kind != Snapshot::kMessage);
|
||||
|
||||
Library& library = Library::ZoneHandle(reader->isolate(), Library::null());
|
||||
reader->AddBackwardReference(object_id, &library);
|
||||
reader->AddBackRef(object_id, &library, kIsDeserialized);
|
||||
|
||||
if (RawObject::IsCreatedFromSnapshot(tags)) {
|
||||
ASSERT(kind != Snapshot::kFull);
|
||||
// Lookup the object as it should already exist in the heap.
|
||||
*reader->StringHandle() ^= reader->ReadObject();
|
||||
*reader->StringHandle() ^= reader->ReadObjectImpl();
|
||||
library = Library::LookupLibrary(*reader->StringHandle());
|
||||
} else {
|
||||
// Allocate library object.
|
||||
|
@ -727,7 +727,7 @@ RawLibrary* Library::ReadFrom(SnapshotReader* reader,
|
|||
// allocations may happen.
|
||||
intptr_t num_flds = (library.raw()->to() - library.raw()->from());
|
||||
for (intptr_t i = 0; i <= num_flds; i++) {
|
||||
*(library.raw()->from() + i) = reader->ReadObject();
|
||||
*(library.raw()->from() + i) = reader->ReadObjectRef();
|
||||
}
|
||||
if (kind != Snapshot::kFull) {
|
||||
library.Register();
|
||||
|
@ -752,7 +752,7 @@ void RawLibrary::WriteTo(SnapshotWriter* writer,
|
|||
if (RawObject::IsCreatedFromSnapshot(writer->GetObjectTags(this))) {
|
||||
ASSERT(kind != Snapshot::kFull);
|
||||
// Write out library URL so that it can be looked up when reading.
|
||||
writer->WriteObject(ptr()->url_);
|
||||
writer->WriteObjectImpl(ptr()->url_);
|
||||
} else {
|
||||
// Write out all non object fields.
|
||||
writer->WriteIntptrValue(ptr()->index_);
|
||||
|
@ -786,7 +786,7 @@ RawLibraryPrefix* LibraryPrefix::ReadFrom(SnapshotReader* reader,
|
|||
// Allocate library prefix object.
|
||||
LibraryPrefix& prefix = LibraryPrefix::ZoneHandle(
|
||||
reader->isolate(), NEW_OBJECT(LibraryPrefix));
|
||||
reader->AddBackwardReference(object_id, &prefix);
|
||||
reader->AddBackRef(object_id, &prefix, kIsDeserialized);
|
||||
|
||||
// Set the object tags.
|
||||
prefix.set_tags(tags);
|
||||
|
@ -799,7 +799,7 @@ RawLibraryPrefix* LibraryPrefix::ReadFrom(SnapshotReader* reader,
|
|||
// allocations may happen.
|
||||
intptr_t num_flds = (prefix.raw()->to() - prefix.raw()->from());
|
||||
for (intptr_t i = 0; i <= num_flds; i++) {
|
||||
*(prefix.raw()->from() + i) = reader->ReadObject();
|
||||
*(prefix.raw()->from() + i) = reader->ReadObjectRef();
|
||||
}
|
||||
|
||||
return prefix.raw();
|
||||
|
@ -941,7 +941,7 @@ RawContext* Context::ReadFrom(SnapshotReader* reader,
|
|||
} else {
|
||||
context = Context::New(num_vars);
|
||||
}
|
||||
reader->AddBackwardReference(object_id, &context);
|
||||
reader->AddBackRef(object_id, &context, kIsDeserialized);
|
||||
|
||||
// Set the object tags.
|
||||
context.set_tags(tags);
|
||||
|
@ -954,7 +954,7 @@ RawContext* Context::ReadFrom(SnapshotReader* reader,
|
|||
// allocations may happen.
|
||||
intptr_t num_flds = (context.raw()->to(num_vars) - context.raw()->from());
|
||||
for (intptr_t i = 0; i <= num_flds; i++) {
|
||||
*(context.raw()->from() + i) = reader->ReadObject();
|
||||
*(context.raw()->from() + i) = reader->ReadObjectRef();
|
||||
}
|
||||
|
||||
return context.raw();
|
||||
|
@ -994,7 +994,7 @@ RawContextScope* ContextScope::ReadFrom(SnapshotReader* reader,
|
|||
intptr_t num_vars = reader->ReadIntptrValue();
|
||||
ContextScope& scope = ContextScope::ZoneHandle(reader->isolate(),
|
||||
ContextScope::New(num_vars));
|
||||
reader->AddBackwardReference(object_id, &scope);
|
||||
reader->AddBackRef(object_id, &scope, kIsDeserialized);
|
||||
|
||||
// Set the object tags.
|
||||
scope.set_tags(tags);
|
||||
|
@ -1004,7 +1004,7 @@ RawContextScope* ContextScope::ReadFrom(SnapshotReader* reader,
|
|||
// allocations may happen.
|
||||
intptr_t num_flds = (scope.raw()->to(num_vars) - scope.raw()->from());
|
||||
for (intptr_t i = 0; i <= num_flds; i++) {
|
||||
*(scope.raw()->from() + i) = reader->ReadObject();
|
||||
*(scope.raw()->from() + i) = reader->ReadObjectRef();
|
||||
}
|
||||
|
||||
return scope.raw();
|
||||
|
@ -1181,7 +1181,7 @@ RawMint* Mint::ReadFrom(SnapshotReader* reader,
|
|||
mint = Mint::New(value, Heap::kNew);
|
||||
}
|
||||
}
|
||||
reader->AddBackwardReference(object_id, &mint);
|
||||
reader->AddBackRef(object_id, &mint, kIsDeserialized);
|
||||
|
||||
// Set the object tags.
|
||||
mint.set_tags(tags);
|
||||
|
@ -1229,7 +1229,7 @@ RawBigint* Bigint::ReadFrom(SnapshotReader* reader,
|
|||
if ((kind != Snapshot::kFull) && RawObject::IsCanonical(tags)) {
|
||||
obj ^= obj.Canonicalize();
|
||||
}
|
||||
reader->AddBackwardReference(object_id, &obj);
|
||||
reader->AddBackRef(object_id, &obj, kIsDeserialized);
|
||||
|
||||
// Set the object tags.
|
||||
obj.set_tags(tags);
|
||||
|
@ -1301,7 +1301,7 @@ RawDouble* Double::ReadFrom(SnapshotReader* reader,
|
|||
dbl = Double::New(value, Heap::kNew);
|
||||
}
|
||||
}
|
||||
reader->AddBackwardReference(object_id, &dbl);
|
||||
reader->AddBackRef(object_id, &dbl, kIsDeserialized);
|
||||
|
||||
// Set the object tags.
|
||||
dbl.set_tags(tags);
|
||||
|
@ -1394,7 +1394,7 @@ RawOneByteString* OneByteString::ReadFrom(SnapshotReader* reader,
|
|||
} else {
|
||||
ReadFromImpl<OneByteString, uint8_t>(reader, &str_obj, len, tags);
|
||||
}
|
||||
reader->AddBackwardReference(object_id, &str_obj);
|
||||
reader->AddBackRef(object_id, &str_obj, kIsDeserialized);
|
||||
return str_obj.raw();
|
||||
}
|
||||
|
||||
|
@ -1425,7 +1425,7 @@ RawTwoByteString* TwoByteString::ReadFrom(SnapshotReader* reader,
|
|||
} else {
|
||||
ReadFromImpl<TwoByteString, uint16_t>(reader, &str_obj, len, tags);
|
||||
}
|
||||
reader->AddBackwardReference(object_id, &str_obj);
|
||||
reader->AddBackRef(object_id, &str_obj, kIsDeserialized);
|
||||
return str_obj.raw();
|
||||
}
|
||||
|
||||
|
@ -1456,7 +1456,7 @@ RawFourByteString* FourByteString::ReadFrom(SnapshotReader* reader,
|
|||
} else {
|
||||
ReadFromImpl<FourByteString, uint32_t>(reader, &str_obj, len, tags);
|
||||
}
|
||||
reader->AddBackwardReference(object_id, &str_obj);
|
||||
reader->AddBackRef(object_id, &str_obj, kIsDeserialized);
|
||||
return str_obj.raw();
|
||||
}
|
||||
|
||||
|
@ -1625,26 +1625,6 @@ void RawBool::WriteTo(SnapshotWriter* writer,
|
|||
}
|
||||
|
||||
|
||||
static void ArrayReadFrom(SnapshotReader* reader,
|
||||
const Array& result,
|
||||
intptr_t len,
|
||||
intptr_t tags) {
|
||||
ASSERT(reader != NULL);
|
||||
|
||||
// Set the object tags.
|
||||
result.set_tags(tags);
|
||||
|
||||
// Setup the object fields.
|
||||
*reader->TypeArgumentsHandle() ^= reader->ReadObject();
|
||||
result.SetTypeArguments(*reader->TypeArgumentsHandle());
|
||||
|
||||
for (intptr_t i = 0; i < len; i++) {
|
||||
*reader->ObjectHandle() = reader->ReadObject();
|
||||
result.SetAt(i, *reader->ObjectHandle());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RawArray* Array::ReadFrom(SnapshotReader* reader,
|
||||
intptr_t object_id,
|
||||
intptr_t tags,
|
||||
|
@ -1653,11 +1633,15 @@ RawArray* Array::ReadFrom(SnapshotReader* reader,
|
|||
|
||||
// Read the length so that we can determine instance size to allocate.
|
||||
intptr_t len = reader->ReadSmiValue();
|
||||
Array& array = Array::ZoneHandle(reader->isolate(),
|
||||
NEW_OBJECT_WITH_LEN(Array, len));
|
||||
reader->AddBackwardReference(object_id, &array);
|
||||
ArrayReadFrom(reader, array, len, tags);
|
||||
return array.raw();
|
||||
Array* array = reinterpret_cast<Array*>(
|
||||
reader->GetBackRef(object_id));
|
||||
if (array == NULL) {
|
||||
array = &(Array::ZoneHandle(reader->isolate(),
|
||||
NEW_OBJECT_WITH_LEN(Array, len)));
|
||||
reader->AddBackRef(object_id, array, kIsDeserialized);
|
||||
}
|
||||
reader->ArrayReadFrom(*array, len, tags);
|
||||
return array->raw();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1669,69 +1653,39 @@ RawImmutableArray* ImmutableArray::ReadFrom(SnapshotReader* reader,
|
|||
|
||||
// Read the length so that we can determine instance size to allocate.
|
||||
intptr_t len = reader->ReadSmiValue();
|
||||
ImmutableArray& array = ImmutableArray::ZoneHandle(
|
||||
reader->isolate(), NEW_OBJECT_WITH_LEN(ImmutableArray, len));
|
||||
reader->AddBackwardReference(object_id, &array);
|
||||
ArrayReadFrom(reader, array, len, tags);
|
||||
return array.raw();
|
||||
}
|
||||
|
||||
|
||||
static void ArrayWriteTo(SnapshotWriter* writer,
|
||||
intptr_t object_id,
|
||||
Snapshot::Kind kind,
|
||||
intptr_t array_kind,
|
||||
intptr_t tags,
|
||||
RawSmi* length,
|
||||
RawAbstractTypeArguments* type_arguments,
|
||||
RawObject* data[]) {
|
||||
ASSERT(writer != NULL);
|
||||
intptr_t len = Smi::Value(length);
|
||||
|
||||
// Write out the serialization header value for this object.
|
||||
writer->WriteSerializationMarker(kInlined, object_id);
|
||||
|
||||
// Write out the class and tags information.
|
||||
writer->WriteObjectHeader(array_kind, tags);
|
||||
|
||||
// Write out the length field.
|
||||
writer->Write<RawObject*>(length);
|
||||
|
||||
// Write out the type arguments.
|
||||
writer->WriteObject(type_arguments);
|
||||
|
||||
// Write out the individual objects.
|
||||
for (intptr_t i = 0; i < len; i++) {
|
||||
writer->WriteObject(data[i]);
|
||||
ImmutableArray* array = reinterpret_cast<ImmutableArray*>(
|
||||
reader->GetBackRef(object_id));
|
||||
if (array == NULL) {
|
||||
array = &(ImmutableArray::ZoneHandle(
|
||||
reader->isolate(), NEW_OBJECT_WITH_LEN(ImmutableArray, len)));
|
||||
reader->AddBackRef(object_id, array, kIsDeserialized);
|
||||
}
|
||||
reader->ArrayReadFrom(*array, len, tags);
|
||||
return array->raw();
|
||||
}
|
||||
|
||||
|
||||
void RawArray::WriteTo(SnapshotWriter* writer,
|
||||
intptr_t object_id,
|
||||
Snapshot::Kind kind) {
|
||||
ArrayWriteTo(writer,
|
||||
object_id,
|
||||
kind,
|
||||
ObjectStore::kArrayClass,
|
||||
writer->GetObjectTags(this),
|
||||
ptr()->length_,
|
||||
ptr()->type_arguments_,
|
||||
ptr()->data());
|
||||
writer->ArrayWriteTo(object_id,
|
||||
ObjectStore::kArrayClass,
|
||||
writer->GetObjectTags(this),
|
||||
ptr()->length_,
|
||||
ptr()->type_arguments_,
|
||||
ptr()->data());
|
||||
}
|
||||
|
||||
|
||||
void RawImmutableArray::WriteTo(SnapshotWriter* writer,
|
||||
intptr_t object_id,
|
||||
Snapshot::Kind kind) {
|
||||
ArrayWriteTo(writer,
|
||||
object_id,
|
||||
kind,
|
||||
ObjectStore::kImmutableArrayClass,
|
||||
writer->GetObjectTags(this),
|
||||
ptr()->length_,
|
||||
ptr()->type_arguments_,
|
||||
ptr()->data());
|
||||
writer->ArrayWriteTo(object_id,
|
||||
ObjectStore::kImmutableArrayClass,
|
||||
writer->GetObjectTags(this),
|
||||
ptr()->length_,
|
||||
ptr()->type_arguments_,
|
||||
ptr()->data());
|
||||
}
|
||||
|
||||
|
||||
|
@ -1749,11 +1703,11 @@ RawGrowableObjectArray* GrowableObjectArray::ReadFrom(SnapshotReader* reader,
|
|||
} else {
|
||||
array = GrowableObjectArray::New(0);
|
||||
}
|
||||
reader->AddBackwardReference(object_id, &array);
|
||||
reader->AddBackRef(object_id, &array, kIsDeserialized);
|
||||
intptr_t length = reader->ReadSmiValue();
|
||||
array.SetLength(length);
|
||||
Array& contents = Array::Handle();
|
||||
contents ^= reader->ReadObject();
|
||||
contents ^= reader->ReadObjectImpl();
|
||||
array.SetData(contents);
|
||||
const AbstractTypeArguments& type_arguments =
|
||||
AbstractTypeArguments::Handle(contents.GetTypeArguments());
|
||||
|
@ -1778,7 +1732,7 @@ void RawGrowableObjectArray::WriteTo(SnapshotWriter* writer,
|
|||
writer->Write<RawObject*>(ptr()->length_);
|
||||
|
||||
// Write out the Array object.
|
||||
writer->WriteObject(ptr()->data_);
|
||||
writer->WriteObjectImpl(ptr()->data_);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1802,7 +1756,7 @@ RawT* ByteArray::ReadFromImpl(SnapshotReader* reader,
|
|||
Heap::Space space = (kind == Snapshot::kFull) ? Heap::kOld : Heap::kNew;
|
||||
HandleT& result =
|
||||
HandleT::ZoneHandle(reader->isolate(), HandleT::New(len, space));
|
||||
reader->AddBackwardReference(object_id, &result);
|
||||
reader->AddBackRef(object_id, &result, kIsDeserialized);
|
||||
|
||||
// Set the object tags.
|
||||
result.set_tags(tags);
|
||||
|
@ -1975,14 +1929,14 @@ RawJSRegExp* JSRegExp::ReadFrom(SnapshotReader* reader,
|
|||
JSRegExp& regex = JSRegExp::ZoneHandle(
|
||||
reader->isolate(),
|
||||
JSRegExp::New(len, (kind == Snapshot::kFull) ? Heap::kOld : Heap::kNew));
|
||||
reader->AddBackwardReference(object_id, ®ex);
|
||||
reader->AddBackRef(object_id, ®ex, kIsDeserialized);
|
||||
|
||||
// Set the object tags.
|
||||
regex.set_tags(tags);
|
||||
|
||||
// Read and Set all the other fields.
|
||||
regex.raw_ptr()->num_bracket_expressions_ = reader->ReadAsSmi();
|
||||
*reader->StringHandle() ^= reader->ReadObject();
|
||||
*reader->StringHandle() ^= reader->ReadObjectImpl();
|
||||
regex.raw_ptr()->pattern_ = (*reader->StringHandle()).raw();
|
||||
regex.raw_ptr()->type_ = reader->ReadIntptrValue();
|
||||
regex.raw_ptr()->flags_ = reader->ReadIntptrValue();
|
||||
|
@ -2011,7 +1965,7 @@ void RawJSRegExp::WriteTo(SnapshotWriter* writer,
|
|||
|
||||
// Write out all the other fields.
|
||||
writer->Write<RawObject*>(ptr()->num_bracket_expressions_);
|
||||
writer->WriteObject(ptr()->pattern_);
|
||||
writer->WriteObjectImpl(ptr()->pattern_);
|
||||
writer->WriteIntptrValue(ptr()->type_);
|
||||
writer->WriteIntptrValue(ptr()->flags_);
|
||||
|
||||
|
|
|
@ -89,12 +89,14 @@ SnapshotReader::SnapshotReader(const Snapshot* snapshot, Isolate* isolate)
|
|||
|
||||
|
||||
RawObject* SnapshotReader::ReadObject() {
|
||||
int64_t value = Read<int64_t>();
|
||||
if ((value & kSmiTagMask) == 0) {
|
||||
return Integer::New((value >> kSmiTagShift));
|
||||
Object& obj = Object::Handle(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((value <= kIntptrMax) && (value >= kIntptrMin));
|
||||
return ReadObjectImpl(value);
|
||||
return obj.raw();
|
||||
}
|
||||
|
||||
|
||||
|
@ -105,13 +107,13 @@ RawClass* SnapshotReader::ReadClassId(intptr_t object_id) {
|
|||
ASSERT((class_header & kSmiTagMask) != 0);
|
||||
Class& cls = Class::ZoneHandle(isolate(), Class::null());
|
||||
cls ^= LookupInternalClass(class_header);
|
||||
AddBackwardReference(object_id, &cls);
|
||||
AddBackRef(object_id, &cls, kIsDeserialized);
|
||||
if (cls.IsNull()) {
|
||||
// Read the library/class information and lookup the class.
|
||||
str_ ^= ReadObjectImpl(class_header);
|
||||
library_ = Library::LookupLibrary(str_);
|
||||
ASSERT(!library_.IsNull());
|
||||
str_ ^= ReadObject();
|
||||
str_ ^= ReadObjectImpl();
|
||||
cls ^= library_.LookupClass(str_);
|
||||
}
|
||||
ASSERT(!cls.IsNull());
|
||||
|
@ -119,9 +121,132 @@ RawClass* SnapshotReader::ReadClassId(intptr_t object_id) {
|
|||
}
|
||||
|
||||
|
||||
void SnapshotReader::AddBackwardReference(intptr_t id, Object* obj) {
|
||||
ASSERT((id - kMaxPredefinedObjectIds) == backward_references_.length());
|
||||
backward_references_.Add(obj);
|
||||
RawObject* SnapshotReader::ReadObjectImpl() {
|
||||
int64_t value = Read<int64_t>();
|
||||
if ((value & kSmiTagMask) == 0) {
|
||||
return Integer::New((value >> kSmiTagShift));
|
||||
}
|
||||
return ReadObjectImpl(value);
|
||||
}
|
||||
|
||||
|
||||
RawObject* SnapshotReader::ReadObjectImpl(intptr_t 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);
|
||||
return ReadInlinedObject(header_value);
|
||||
}
|
||||
|
||||
|
||||
RawObject* SnapshotReader::ReadObjectRef() {
|
||||
int64_t value = Read<int64_t>();
|
||||
if ((value & kSmiTagMask) == 0) {
|
||||
return Integer::New((value >> kSmiTagShift));
|
||||
}
|
||||
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);
|
||||
intptr_t object_id = header_value;
|
||||
ASSERT(GetBackRef(object_id) == NULL);
|
||||
|
||||
// Read the class header information and lookup the class.
|
||||
intptr_t class_header = ReadIntptrValue();
|
||||
|
||||
// Since we are only reading an object reference, If it is an instance kind
|
||||
// then we only need to figure out the class of the object and allocate an
|
||||
// instance of it. The individual fields will be read later.
|
||||
if (SerializedHeaderData::decode(class_header) == kInstanceId) {
|
||||
Instance& result = Instance::ZoneHandle(isolate(), Instance::null());
|
||||
AddBackRef(object_id, &result, kIsNotDeserialized);
|
||||
|
||||
cls_ ^= ReadObjectImpl(); // Read class information.
|
||||
ASSERT(!cls_.IsNull());
|
||||
intptr_t instance_size = cls_.instance_size();
|
||||
ASSERT(instance_size > 0);
|
||||
if (kind_ == Snapshot::kFull) {
|
||||
result ^= AllocateUninitialized(cls_, instance_size);
|
||||
} else {
|
||||
result ^= Object::Allocate(cls_, instance_size, Heap::kNew);
|
||||
}
|
||||
return result.raw();
|
||||
} else {
|
||||
ASSERT((class_header & kSmiTagMask) != 0);
|
||||
cls_ ^= LookupInternalClass(class_header);
|
||||
ASSERT(!cls_.IsNull());
|
||||
}
|
||||
|
||||
// Similarly Array and ImmutableArray objects are also similarly only
|
||||
// allocated here, the individual array elements are read later.
|
||||
ObjectKind obj_kind = cls_.instance_kind();
|
||||
if (obj_kind == Array::kInstanceKind) {
|
||||
// Read the length and allocate an object based on the len.
|
||||
intptr_t len = ReadSmiValue();
|
||||
Array& array = Array::ZoneHandle(
|
||||
isolate(),
|
||||
(kind_ == Snapshot::kFull) ? NewArray(len) : Array::New(len));
|
||||
AddBackRef(object_id, &array, kIsNotDeserialized);
|
||||
|
||||
return array.raw();
|
||||
}
|
||||
if (obj_kind == ImmutableArray::kInstanceKind) {
|
||||
// Read the length and allocate an object based on the len.
|
||||
intptr_t len = ReadSmiValue();
|
||||
ImmutableArray& array = ImmutableArray::ZoneHandle(
|
||||
isolate(),
|
||||
(kind_ == Snapshot::kFull) ?
|
||||
NewImmutableArray(len) : ImmutableArray::New(len));
|
||||
AddBackRef(object_id, &array, kIsNotDeserialized);
|
||||
|
||||
return array.raw();
|
||||
}
|
||||
|
||||
// For all other internal VM classes we read the object inline.
|
||||
intptr_t tags = ReadIntptrValue();
|
||||
switch (obj_kind) {
|
||||
#define SNAPSHOT_READ(clazz) \
|
||||
case clazz::kInstanceKind: { \
|
||||
obj_ = clazz::ReadFrom(this, object_id, tags, kind_); \
|
||||
break; \
|
||||
}
|
||||
CLASS_LIST_NO_OBJECT(SNAPSHOT_READ)
|
||||
#undef SNAPSHOT_READ
|
||||
default: UNREACHABLE(); break;
|
||||
}
|
||||
if (kind_ == Snapshot::kFull) {
|
||||
obj_.SetCreatedFromSnapshot();
|
||||
}
|
||||
return obj_.raw();
|
||||
}
|
||||
|
||||
|
||||
void SnapshotReader::AddBackRef(intptr_t id,
|
||||
Object* obj,
|
||||
DeserializeState state) {
|
||||
intptr_t index = (id - kMaxPredefinedObjectIds);
|
||||
ASSERT(index == backward_references_.length());
|
||||
BackRefNode* node = new BackRefNode(obj, state);
|
||||
ASSERT(node != NULL);
|
||||
backward_references_.Add(node);
|
||||
}
|
||||
|
||||
|
||||
Object* SnapshotReader::GetBackRef(intptr_t id) {
|
||||
ASSERT(id >= kMaxPredefinedObjectIds);
|
||||
intptr_t index = (id - kMaxPredefinedObjectIds);
|
||||
if (index < backward_references_.length()) {
|
||||
return backward_references_[index]->reference();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -139,7 +264,13 @@ void SnapshotReader::ReadFullSnapshot() {
|
|||
// Read in all the objects stored in the object store.
|
||||
intptr_t num_flds = (object_store->to() - object_store->from());
|
||||
for (intptr_t i = 0; i <= num_flds; i++) {
|
||||
*(object_store->from() + i) = ReadObject();
|
||||
*(object_store->from() + i) = ReadObjectImpl();
|
||||
}
|
||||
for (intptr_t i = 0; i < backward_references_.length(); i++) {
|
||||
if (!backward_references_[i]->is_deserialized()) {
|
||||
ReadObjectImpl();
|
||||
backward_references_[i]->set_state(kIsDeserialized);
|
||||
}
|
||||
}
|
||||
|
||||
// Setup native resolver for bootstrap impl.
|
||||
|
@ -378,18 +509,6 @@ RawObject* SnapshotReader::AllocateUninitialized(const Class& cls,
|
|||
}
|
||||
|
||||
|
||||
RawObject* SnapshotReader::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);
|
||||
}
|
||||
ASSERT(header_type == kInlined);
|
||||
return ReadInlinedObject(header_value);
|
||||
}
|
||||
|
||||
|
||||
RawObject* SnapshotReader::ReadIndexedObject(intptr_t object_id) {
|
||||
if (object_id == Object::kNullObject) {
|
||||
// This is a singleton null object, return it.
|
||||
|
@ -412,10 +531,8 @@ RawObject* SnapshotReader::ReadIndexedObject(intptr_t object_id) {
|
|||
}
|
||||
}
|
||||
|
||||
ASSERT(object_id >= kMaxPredefinedObjectIds);
|
||||
intptr_t index = object_id - kMaxPredefinedObjectIds;
|
||||
ASSERT(index < backward_references_.length());
|
||||
return backward_references_[index]->raw();
|
||||
Object* object = GetBackRef(object_id);
|
||||
return object->raw();
|
||||
}
|
||||
|
||||
|
||||
|
@ -425,31 +542,38 @@ RawObject* SnapshotReader::ReadInlinedObject(intptr_t object_id) {
|
|||
intptr_t tags = ReadIntptrValue();
|
||||
if (SerializedHeaderData::decode(class_header) == kInstanceId) {
|
||||
// Object is regular dart instance.
|
||||
Instance& result = Instance::ZoneHandle(isolate(), Instance::null());
|
||||
AddBackwardReference(object_id, &result);
|
||||
|
||||
cls_ ^= ReadObject();
|
||||
ASSERT(!cls_.IsNull());
|
||||
intptr_t instance_size = cls_.instance_size();
|
||||
ASSERT(instance_size > 0);
|
||||
// Allocate the instance and read in all the fields for the object.
|
||||
if (kind_ == Snapshot::kFull) {
|
||||
result ^= AllocateUninitialized(cls_, instance_size);
|
||||
Instance* result = reinterpret_cast<Instance*>(GetBackRef(object_id));
|
||||
intptr_t instance_size = 0;
|
||||
if (result == NULL) {
|
||||
result = &(Instance::ZoneHandle(isolate(), Instance::null()));
|
||||
AddBackRef(object_id, result, kIsDeserialized);
|
||||
cls_ ^= ReadObjectImpl();
|
||||
ASSERT(!cls_.IsNull());
|
||||
instance_size = cls_.instance_size();
|
||||
ASSERT(instance_size > 0);
|
||||
// Allocate the instance and read in all the fields for the object.
|
||||
if (kind_ == Snapshot::kFull) {
|
||||
*result ^= AllocateUninitialized(cls_, instance_size);
|
||||
} else {
|
||||
*result ^= Object::Allocate(cls_, instance_size, Heap::kNew);
|
||||
}
|
||||
} else {
|
||||
result ^= Object::Allocate(cls_, instance_size, Heap::kNew);
|
||||
cls_ ^= ReadObjectImpl();
|
||||
ASSERT(!cls_.IsNull());
|
||||
instance_size = cls_.instance_size();
|
||||
}
|
||||
intptr_t offset = Object::InstanceSize();
|
||||
while (offset < instance_size) {
|
||||
obj_ = ReadObject();
|
||||
result.SetFieldAtOffset(offset, obj_);
|
||||
obj_ = ReadObjectRef();
|
||||
result->SetFieldAtOffset(offset, obj_);
|
||||
offset += kWordSize;
|
||||
}
|
||||
if (kind_ == Snapshot::kFull) {
|
||||
result.SetCreatedFromSnapshot();
|
||||
} else if (result.IsCanonical()) {
|
||||
result = result.Canonicalize();
|
||||
result->SetCreatedFromSnapshot();
|
||||
} else if (result->IsCanonical()) {
|
||||
*result = result->Canonicalize();
|
||||
}
|
||||
return result.raw();
|
||||
return result->raw();
|
||||
} else {
|
||||
ASSERT((class_header & kSmiTagMask) != 0);
|
||||
cls_ ^= LookupInternalClass(class_header);
|
||||
|
@ -472,26 +596,123 @@ RawObject* SnapshotReader::ReadInlinedObject(intptr_t object_id) {
|
|||
}
|
||||
|
||||
|
||||
void SnapshotWriter::WriteObject(RawObject* rawobj) {
|
||||
// First check if object can be written as a simple predefined type.
|
||||
if (CheckAndWritePredefinedObject(rawobj)) {
|
||||
return;
|
||||
void SnapshotReader::ArrayReadFrom(const Array& result,
|
||||
intptr_t len,
|
||||
intptr_t tags) {
|
||||
// Set the object tags.
|
||||
result.set_tags(tags);
|
||||
|
||||
// Setup the object fields.
|
||||
*TypeArgumentsHandle() ^= ReadObjectImpl();
|
||||
result.SetTypeArguments(*TypeArgumentsHandle());
|
||||
|
||||
for (intptr_t i = 0; i < len; i++) {
|
||||
*ObjectHandle() = ReadObjectRef();
|
||||
result.SetAt(i, *ObjectHandle());
|
||||
}
|
||||
// Now write the object out inline in the stream as follows:
|
||||
// - Object is seen for the first time (inlined as follows):
|
||||
// (object size in multiples of kObjectAlignment | 0x1)
|
||||
// serialized fields of the object
|
||||
// ......
|
||||
WriteInlinedObject(rawobj);
|
||||
}
|
||||
|
||||
|
||||
void SnapshotWriter::UnmarkAll() {
|
||||
NoGCScope no_gc;
|
||||
for (intptr_t i = 0; i < forward_list_.length(); i++) {
|
||||
RawObject* raw = forward_list_[i]->raw();
|
||||
raw->ptr()->tags_ = forward_list_[i]->tags(); // Restore original tags.
|
||||
void SnapshotWriter::WriteObject(RawObject* rawobj) {
|
||||
WriteObjectImpl(rawobj);
|
||||
WriteForwardedObjects();
|
||||
}
|
||||
|
||||
|
||||
void SnapshotWriter::WriteObjectRef(RawObject* raw) {
|
||||
// First check if object can be written as a simple predefined type.
|
||||
if (CheckAndWritePredefinedObject(raw)) {
|
||||
return;
|
||||
}
|
||||
// Check if object has already been serialized, in that
|
||||
// case just write the object id out.
|
||||
uword tags = raw->ptr()->tags_;
|
||||
if (SerializedHeaderTag::decode(tags) == kObjectId) {
|
||||
intptr_t id = SerializedHeaderData::decode(tags);
|
||||
WriteIndexedObject(id);
|
||||
return;
|
||||
}
|
||||
|
||||
NoGCScope no_gc;
|
||||
RawClass* cls = class_table_->At(RawObject::ClassIdTag::decode(tags));
|
||||
|
||||
ObjectKind obj_kind = cls->ptr()->instance_kind_;
|
||||
if (obj_kind == Instance::kInstanceKind) {
|
||||
// Object is being referenced, add it to the forward ref list and mark
|
||||
// it so that future references to this object in the snapshot will use
|
||||
// this object id. Mark it as not having been serialized yet so that we
|
||||
// will serialize the object when we go through the forward list.
|
||||
intptr_t object_id = MarkObject(raw, kIsNotSerialized);
|
||||
|
||||
// Write out the serialization header value for this object.
|
||||
WriteSerializationMarker(kInlined, object_id);
|
||||
|
||||
// Indicate this is an instance object.
|
||||
WriteIntptrValue(SerializedHeaderData::encode(kInstanceId));
|
||||
|
||||
// Write out the class information for this object.
|
||||
WriteObjectImpl(cls);
|
||||
|
||||
return;
|
||||
}
|
||||
if (obj_kind == Array::kInstanceKind) {
|
||||
// Object is being referenced, add it to the forward ref list and mark
|
||||
// it so that future references to this object in the snapshot will use
|
||||
// this object id. Mark it as not having been serialized yet so that we
|
||||
// will serialize the object when we go through the forward list.
|
||||
intptr_t object_id = MarkObject(raw, kIsNotSerialized);
|
||||
|
||||
RawArray* rawarray = reinterpret_cast<RawArray*>(raw);
|
||||
|
||||
// Write out the serialization header value for this object.
|
||||
WriteSerializationMarker(kInlined, object_id);
|
||||
|
||||
// Write out the class information.
|
||||
WriteIndexedObject(ObjectStore::kArrayClass);
|
||||
|
||||
// Write out the length field.
|
||||
Write<RawObject*>(rawarray->ptr()->length_);
|
||||
|
||||
return;
|
||||
}
|
||||
if (obj_kind == ImmutableArray::kInstanceKind) {
|
||||
// Object is being referenced, add it to the forward ref list and mark
|
||||
// it so that future references to this object in the snapshot will use
|
||||
// this object id. Mark it as not having been serialized yet so that we
|
||||
// will serialize the object when we go through the forward list.
|
||||
intptr_t object_id = MarkObject(raw, kIsNotSerialized);
|
||||
|
||||
RawArray* rawarray = reinterpret_cast<RawArray*>(raw);
|
||||
|
||||
// Write out the serialization header value for this object.
|
||||
WriteSerializationMarker(kInlined, object_id);
|
||||
|
||||
// Write out the class information.
|
||||
WriteIndexedObject(ObjectStore::kImmutableArrayClass);
|
||||
|
||||
// Write out the length field.
|
||||
Write<RawObject*>(rawarray->ptr()->length_);
|
||||
|
||||
return;
|
||||
}
|
||||
// Object is being referenced, add it to the forward ref list and mark
|
||||
// it so that future references to this object in the snapshot will use
|
||||
// this object id. Mark it as not having been serialized yet so that we
|
||||
// will serialize the object when we go through the forward list.
|
||||
intptr_t object_id = MarkObject(raw, kIsSerialized);
|
||||
switch (obj_kind) {
|
||||
#define SNAPSHOT_WRITE(clazz) \
|
||||
case clazz::kInstanceKind: { \
|
||||
Raw##clazz* raw_obj = reinterpret_cast<Raw##clazz*>(raw); \
|
||||
raw_obj->WriteTo(this, object_id, kind_); \
|
||||
return; \
|
||||
} \
|
||||
|
||||
CLASS_LIST_NO_OBJECT(SNAPSHOT_WRITE)
|
||||
#undef SNAPSHOT_WRITE
|
||||
default: break;
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
|
@ -504,9 +725,12 @@ void SnapshotWriter::WriteFullSnapshot() {
|
|||
|
||||
// Write out all the objects in the object store of the isolate which
|
||||
// is the root set for all dart allocated objects at this point.
|
||||
SnapshotWriterVisitor visitor(this);
|
||||
SnapshotWriterVisitor visitor(this, false);
|
||||
object_store->VisitObjectPointers(&visitor);
|
||||
|
||||
// Write out all forwarded objects.
|
||||
WriteForwardedObjects();
|
||||
|
||||
// Finalize the snapshot buffer.
|
||||
FinalizeBuffer();
|
||||
}
|
||||
|
@ -523,7 +747,7 @@ uword SnapshotWriter::GetObjectTags(RawObject* raw) {
|
|||
}
|
||||
|
||||
|
||||
intptr_t SnapshotWriter::MarkObject(RawObject* raw) {
|
||||
intptr_t SnapshotWriter::MarkObject(RawObject* raw, SerializeState state) {
|
||||
NoGCScope no_gc;
|
||||
intptr_t object_id = forward_list_.length() + kMaxPredefinedObjectIds;
|
||||
ASSERT(object_id <= kMaxObjectId);
|
||||
|
@ -532,13 +756,22 @@ intptr_t SnapshotWriter::MarkObject(RawObject* raw) {
|
|||
value = SerializedHeaderData::update(object_id, value);
|
||||
uword tags = raw->ptr()->tags_;
|
||||
raw->ptr()->tags_ = value;
|
||||
ForwardObjectNode* node = new ForwardObjectNode(raw, tags);
|
||||
ForwardObjectNode* node = new ForwardObjectNode(raw, tags, state);
|
||||
ASSERT(node != NULL);
|
||||
forward_list_.Add(node);
|
||||
return object_id;
|
||||
}
|
||||
|
||||
|
||||
void SnapshotWriter::UnmarkAll() {
|
||||
NoGCScope no_gc;
|
||||
for (intptr_t i = 0; i < forward_list_.length(); i++) {
|
||||
RawObject* raw = forward_list_[i]->raw();
|
||||
raw->ptr()->tags_ = forward_list_[i]->tags(); // Restore original tags.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool SnapshotWriter::CheckAndWritePredefinedObject(RawObject* rawobj) {
|
||||
// Check if object can be written in one of the following ways:
|
||||
// - Smi: the Smi value is written as is (last bit is not tagged).
|
||||
|
@ -603,30 +836,51 @@ bool SnapshotWriter::CheckAndWritePredefinedObject(RawObject* rawobj) {
|
|||
}
|
||||
}
|
||||
|
||||
// Check if object has already been serialized, in that
|
||||
// case just write the object id out.
|
||||
uword tags = rawobj->ptr()->tags_;
|
||||
if (SerializedHeaderTag::decode(tags) == kObjectId) {
|
||||
intptr_t id = SerializedHeaderData::decode(tags);
|
||||
WriteIndexedObject(id);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void SnapshotWriter::WriteInlinedObject(RawObject* raw) {
|
||||
NoGCScope no_gc;
|
||||
void SnapshotWriter::WriteObjectImpl(RawObject* raw) {
|
||||
// First check if object can be written as a simple predefined type.
|
||||
if (CheckAndWritePredefinedObject(raw)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if object has already been serialized, in that
|
||||
// case just write the object id out.
|
||||
uword tags = raw->ptr()->tags_;
|
||||
RawClass* cls = class_table_->At(RawObject::ClassIdTag::decode(tags));
|
||||
if (SerializedHeaderTag::decode(tags) == kObjectId) {
|
||||
intptr_t id = SerializedHeaderData::decode(tags);
|
||||
WriteIndexedObject(id);
|
||||
return;
|
||||
}
|
||||
|
||||
// Object is being serialized, add it to the forward ref list and mark
|
||||
// it so that future references to this object in the snapshot will use
|
||||
// an object id, instead of trying to serialize it again.
|
||||
intptr_t object_id = MarkObject(raw);
|
||||
MarkObject(raw, kIsSerialized);
|
||||
|
||||
WriteInlinedObject(raw);
|
||||
}
|
||||
|
||||
|
||||
void SnapshotWriter::WriteInlinedObject(RawObject* raw) {
|
||||
// Assert object is not a simple predefined type.
|
||||
ASSERT(!CheckAndWritePredefinedObject(raw));
|
||||
|
||||
// Now write the object out inline in the stream as follows:
|
||||
// - Object is seen for the first time (inlined as follows):
|
||||
// (object size in multiples of kObjectAlignment | 0x1)
|
||||
// serialized fields of the object
|
||||
// ......
|
||||
NoGCScope no_gc;
|
||||
uword tags = raw->ptr()->tags_;
|
||||
ASSERT(SerializedHeaderTag::decode(tags) == kObjectId);
|
||||
intptr_t object_id = SerializedHeaderData::decode(tags);
|
||||
tags = forward_list_[object_id - kMaxPredefinedObjectIds]->tags();
|
||||
RawClass* cls = class_table_->At(RawObject::ClassIdTag::decode(tags));
|
||||
ObjectKind kind = cls->ptr()->instance_kind_;
|
||||
|
||||
if (kind == Instance::kInstanceKind) {
|
||||
// Object is regular dart instance.
|
||||
// TODO(5411462): figure out what we need to do if an object with native
|
||||
|
@ -645,12 +899,12 @@ void SnapshotWriter::WriteInlinedObject(RawObject* raw) {
|
|||
WriteIntptrValue(tags);
|
||||
|
||||
// Write out the class information for this object.
|
||||
WriteObject(cls);
|
||||
WriteObjectImpl(cls);
|
||||
|
||||
// Write out all the fields for the object.
|
||||
intptr_t offset = Object::InstanceSize();
|
||||
while (offset < instance_size) {
|
||||
WriteObject(*reinterpret_cast<RawObject**>(
|
||||
WriteObjectRef(*reinterpret_cast<RawObject**>(
|
||||
reinterpret_cast<uword>(raw->ptr()) + offset));
|
||||
offset += kWordSize;
|
||||
}
|
||||
|
@ -672,6 +926,25 @@ void SnapshotWriter::WriteInlinedObject(RawObject* raw) {
|
|||
}
|
||||
|
||||
|
||||
void SnapshotWriter::WriteForwardedObjects() {
|
||||
// Write out all objects that were added to the forward list and have
|
||||
// not been serialized yet. These would typically be fields of instance
|
||||
// objects, arrays or immutable arrays (this is done in order to avoid
|
||||
// deep recursive calls to WriteObjectImpl).
|
||||
// NOTE: The forward list might grow as we process the list.
|
||||
for (intptr_t i = 0; i < forward_list_.length(); i++) {
|
||||
if (!forward_list_[i]->is_serialized()) {
|
||||
// Write the object out in the stream.
|
||||
RawObject* raw = forward_list_[i]->raw();
|
||||
WriteInlinedObject(raw);
|
||||
|
||||
// Mark object as serialized.
|
||||
forward_list_[i]->set_state(kIsSerialized);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SnapshotWriter::WriteClassId(RawClass* cls) {
|
||||
ASSERT(kind_ != Snapshot::kFull);
|
||||
int id = object_store()->GetClassIndex(cls);
|
||||
|
@ -681,13 +954,40 @@ void SnapshotWriter::WriteClassId(RawClass* cls) {
|
|||
// TODO(5411462): Should restrict this to only core-lib classes in this
|
||||
// case.
|
||||
// Write out the class and tags information.
|
||||
WriteObjectHeader(Object::kClassClass, cls->ptr()->tags_);
|
||||
WriteObjectHeader(Object::kClassClass, GetObjectTags(cls));
|
||||
|
||||
// Write out the library url and class name.
|
||||
RawLibrary* library = cls->ptr()->library_;
|
||||
ASSERT(library != Library::null());
|
||||
WriteObject(library->ptr()->url_);
|
||||
WriteObject(cls->ptr()->name_);
|
||||
WriteObjectImpl(library->ptr()->url_);
|
||||
WriteObjectImpl(cls->ptr()->name_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SnapshotWriter::ArrayWriteTo(intptr_t object_id,
|
||||
intptr_t array_kind,
|
||||
intptr_t tags,
|
||||
RawSmi* length,
|
||||
RawAbstractTypeArguments* type_arguments,
|
||||
RawObject* data[]) {
|
||||
intptr_t len = Smi::Value(length);
|
||||
|
||||
// Write out the serialization header value for this object.
|
||||
WriteSerializationMarker(kInlined, object_id);
|
||||
|
||||
// Write out the class and tags information.
|
||||
WriteObjectHeader(array_kind, tags);
|
||||
|
||||
// Write out the length field.
|
||||
Write<RawObject*>(length);
|
||||
|
||||
// Write out the type arguments.
|
||||
WriteObjectImpl(type_arguments);
|
||||
|
||||
// Write out the individual object ids.
|
||||
for (intptr_t i = 0; i < len; i++) {
|
||||
WriteObjectRef(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -706,7 +1006,11 @@ void ScriptSnapshotWriter::WriteScriptSnapshot(const Library& lib) {
|
|||
void SnapshotWriterVisitor::VisitPointers(RawObject** first, RawObject** last) {
|
||||
for (RawObject** current = first; current <= last; current++) {
|
||||
RawObject* raw_obj = *current;
|
||||
writer_->WriteObject(raw_obj);
|
||||
if (as_references_) {
|
||||
writer_->WriteObjectRef(raw_obj);
|
||||
} else {
|
||||
writer_->WriteObjectImpl(raw_obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,11 +18,13 @@ namespace dart {
|
|||
// Forward declarations.
|
||||
class AbstractType;
|
||||
class AbstractTypeArguments;
|
||||
class Array;
|
||||
class Class;
|
||||
class Heap;
|
||||
class Library;
|
||||
class Object;
|
||||
class ObjectStore;
|
||||
class RawAbstractTypeArguments;
|
||||
class RawArray;
|
||||
class RawBigint;
|
||||
class RawClass;
|
||||
|
@ -84,6 +86,18 @@ class SerializedHeaderData : public BitField<intptr_t,
|
|||
};
|
||||
|
||||
|
||||
enum DeserializeState {
|
||||
kIsDeserialized = 0,
|
||||
kIsNotDeserialized = 1,
|
||||
};
|
||||
|
||||
|
||||
enum SerializeState {
|
||||
kIsSerialized = 0,
|
||||
kIsNotSerialized = 1,
|
||||
};
|
||||
|
||||
|
||||
// Structure capturing the raw snapshot.
|
||||
class Snapshot {
|
||||
public:
|
||||
|
@ -355,10 +369,11 @@ class SnapshotReader : public BaseReader {
|
|||
// Reads an object.
|
||||
RawObject* ReadObject();
|
||||
|
||||
RawClass* ReadClassId(intptr_t object_id);
|
||||
|
||||
// Add object to backward references.
|
||||
void AddBackwardReference(intptr_t id, Object* obj);
|
||||
void AddBackRef(intptr_t id, Object* obj, DeserializeState state);
|
||||
|
||||
// Get an object from the backward references list.
|
||||
Object* GetBackRef(intptr_t id);
|
||||
|
||||
// Read a full snap shot.
|
||||
void ReadFullSnapshot();
|
||||
|
@ -390,11 +405,28 @@ class SnapshotReader : public BaseReader {
|
|||
RawGrowableObjectArray* NewGrowableObjectArray();
|
||||
|
||||
private:
|
||||
class BackRefNode : public ZoneAllocated {
|
||||
public:
|
||||
BackRefNode(Object* reference, DeserializeState state)
|
||||
: reference_(reference), state_(state) {}
|
||||
Object* reference() const { return reference_; }
|
||||
bool is_deserialized() const { return state_ == kIsDeserialized; }
|
||||
void set_state(DeserializeState state) { state_ = state; }
|
||||
|
||||
private:
|
||||
Object* reference_;
|
||||
DeserializeState state_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(BackRefNode);
|
||||
};
|
||||
|
||||
// Allocate uninitialized objects, this is used when reading a full snapshot.
|
||||
RawObject* AllocateUninitialized(const Class& cls, intptr_t size);
|
||||
|
||||
// Internal implementation of ReadObject once the header value is read.
|
||||
RawClass* ReadClassId(intptr_t object_id);
|
||||
RawObject* ReadObjectImpl();
|
||||
RawObject* ReadObjectImpl(intptr_t header);
|
||||
RawObject* ReadObjectRef();
|
||||
|
||||
// Read an object that was serialized as an Id (singleton, object store,
|
||||
// or an object that was already serialized before).
|
||||
|
@ -406,6 +438,8 @@ class SnapshotReader : public BaseReader {
|
|||
// Based on header field check to see if it is an internal VM class.
|
||||
RawClass* LookupInternalClass(intptr_t class_header);
|
||||
|
||||
void ArrayReadFrom(const Array& result, intptr_t len, intptr_t tags);
|
||||
|
||||
Snapshot::Kind kind_; // Indicates type of snapshot(full, script, message).
|
||||
Isolate* isolate_; // Current isolate.
|
||||
Class& cls_; // Temporary Class handle.
|
||||
|
@ -414,8 +448,27 @@ class SnapshotReader : public BaseReader {
|
|||
Library& library_; // Temporary library handle.
|
||||
AbstractType& type_; // Temporary type handle.
|
||||
AbstractTypeArguments& type_arguments_; // Temporary type argument handle.
|
||||
GrowableArray<Object*> backward_references_;
|
||||
GrowableArray<BackRefNode*> backward_references_;
|
||||
|
||||
friend class Array;
|
||||
friend class Class;
|
||||
friend class Context;
|
||||
friend class ContextScope;
|
||||
friend class Field;
|
||||
friend class Function;
|
||||
friend class GrowableObjectArray;
|
||||
friend class ImmutableArray;
|
||||
friend class InstantiatedTypeArguments;
|
||||
friend class JSRegExp;
|
||||
friend class Library;
|
||||
friend class LibraryPrefix;
|
||||
friend class LiteralToken;
|
||||
friend class Script;
|
||||
friend class TokenStream;
|
||||
friend class Type;
|
||||
friend class TypeArguments;
|
||||
friend class TypeParameter;
|
||||
friend class UnresolvedClass;
|
||||
DISALLOW_COPY_AND_ASSIGN(SnapshotReader);
|
||||
};
|
||||
|
||||
|
@ -508,11 +561,6 @@ class SnapshotWriter : public BaseWriter {
|
|||
// Serialize an object into the buffer.
|
||||
void WriteObject(RawObject* raw);
|
||||
|
||||
void WriteClassId(RawClass* cls);
|
||||
|
||||
// Unmark all objects that were marked as forwarded for serializing.
|
||||
void UnmarkAll();
|
||||
|
||||
// Writes a full snapshot of the Isolate.
|
||||
void WriteFullSnapshot();
|
||||
|
||||
|
@ -521,22 +569,37 @@ class SnapshotWriter : public BaseWriter {
|
|||
private:
|
||||
class ForwardObjectNode : public ZoneAllocated {
|
||||
public:
|
||||
ForwardObjectNode(RawObject* raw, uword tags) : raw_(raw), tags_(tags) {}
|
||||
ForwardObjectNode(RawObject* raw, uword tags, SerializeState state)
|
||||
: raw_(raw), tags_(tags), state_(state) {}
|
||||
RawObject* raw() const { return raw_; }
|
||||
uword tags() const { return tags_; }
|
||||
bool is_serialized() const { return state_ == kIsSerialized; }
|
||||
void set_state(SerializeState value) { state_ = value; }
|
||||
|
||||
private:
|
||||
RawObject* raw_;
|
||||
uword tags_;
|
||||
SerializeState state_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ForwardObjectNode);
|
||||
};
|
||||
|
||||
intptr_t MarkObject(RawObject* raw);
|
||||
intptr_t MarkObject(RawObject* raw, SerializeState state);
|
||||
void UnmarkAll();
|
||||
|
||||
bool CheckAndWritePredefinedObject(RawObject* raw);
|
||||
|
||||
void WriteObjectRef(RawObject* raw);
|
||||
void WriteClassId(RawClass* cls);
|
||||
void WriteObjectImpl(RawObject* raw);
|
||||
void WriteInlinedObject(RawObject* raw);
|
||||
void WriteForwardedObjects();
|
||||
void ArrayWriteTo(intptr_t object_id,
|
||||
intptr_t array_kind,
|
||||
intptr_t tags,
|
||||
RawSmi* length,
|
||||
RawAbstractTypeArguments* type_arguments,
|
||||
RawObject* data[]);
|
||||
|
||||
ObjectStore* object_store() const { return object_store_; }
|
||||
|
||||
|
@ -545,6 +608,17 @@ class SnapshotWriter : public BaseWriter {
|
|||
ClassTable* class_table_; // Class table for the class index to class lookup.
|
||||
GrowableArray<ForwardObjectNode*> forward_list_;
|
||||
|
||||
friend class RawArray;
|
||||
friend class RawClass;
|
||||
friend class RawGrowableObjectArray;
|
||||
friend class RawImmutableArray;
|
||||
friend class RawJSRegExp;
|
||||
friend class RawLibrary;
|
||||
friend class RawLiteralToken;
|
||||
friend class RawScript;
|
||||
friend class RawTokenStream;
|
||||
friend class RawTypeArguments;
|
||||
friend class SnapshotWriterVisitor;
|
||||
DISALLOW_COPY_AND_ASSIGN(SnapshotWriter);
|
||||
};
|
||||
|
||||
|
@ -571,12 +645,20 @@ class ScriptSnapshotWriter : public SnapshotWriter {
|
|||
class SnapshotWriterVisitor : public ObjectPointerVisitor {
|
||||
public:
|
||||
explicit SnapshotWriterVisitor(SnapshotWriter* writer)
|
||||
: ObjectPointerVisitor(Isolate::Current()), writer_(writer) {}
|
||||
: ObjectPointerVisitor(Isolate::Current()),
|
||||
writer_(writer),
|
||||
as_references_(true) {}
|
||||
|
||||
SnapshotWriterVisitor(SnapshotWriter* writer, bool as_references)
|
||||
: ObjectPointerVisitor(Isolate::Current()),
|
||||
writer_(writer),
|
||||
as_references_(as_references) {}
|
||||
|
||||
virtual void VisitPointers(RawObject** first, RawObject** last);
|
||||
|
||||
private:
|
||||
SnapshotWriter* writer_;
|
||||
bool as_references_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(SnapshotWriterVisitor);
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue