blob: 60a22ec0e70de05a4032b9e9de60055461ae7820 [file] [log] [blame]
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/bigint_operations.h"
#include "vm/object.h"
#include "vm/object_store.h"
#include "vm/snapshot.h"
#include "vm/symbols.h"
#include "vm/visitor.h"
namespace dart {
DECLARE_FLAG(bool, error_on_malformed_type);
#define NEW_OBJECT(type) \
((kind == Snapshot::kFull) ? reader->New##type() : type::New())
#define NEW_OBJECT_WITH_LEN(type, len) \
((kind == Snapshot::kFull) ? reader->New##type(len) : type::New(len))
#define NEW_OBJECT_WITH_LEN_SPACE(type, len, kind) \
((kind == Snapshot::kFull) ? \
reader->New##type(len) : type::New(len, HEAP_SPACE(kind)))
static uword BigintAllocator(intptr_t size) {
Zone* zone = Isolate::Current()->current_zone();
return zone->AllocUnsafe(size);
}
RawClass* Class::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
ASSERT(reader != NULL);
Class& cls = Class::ZoneHandle(reader->isolate(), Class::null());
if ((kind == Snapshot::kFull) ||
(kind == Snapshot::kScript && !RawObject::IsCreatedFromSnapshot(tags))) {
// Read in the base information.
intptr_t class_id = reader->ReadIntptrValue();
// Allocate class object of specified kind.
if (kind == Snapshot::kFull) {
cls = reader->NewClass(class_id);
} else {
if (class_id < kNumPredefinedCids) {
ASSERT((class_id >= kInstanceCid) && (class_id <= kDartFunctionCid));
cls = reader->isolate()->class_table()->At(class_id);
} else {
cls = New<Instance>(kIllegalCid);
}
}
reader->AddBackRef(object_id, &cls, kIsDeserialized);
// Set the object tags.
cls.set_tags(tags);
// Set all non object fields.
cls.set_instance_size_in_words(reader->ReadIntptrValue());
cls.set_type_arguments_field_offset_in_words(reader->ReadIntptrValue());
cls.set_next_field_offset_in_words(reader->ReadIntptrValue());
cls.set_num_native_fields(reader->ReadIntptrValue());
cls.set_token_pos(reader->ReadIntptrValue());
cls.set_state_bits(reader->Read<uint8_t>());
// Set all the object fields.
// TODO(5411462): Need to assert No GC can happen here, even though
// 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->ReadObjectRef();
}
} else {
cls ^= reader->ReadClassId(object_id);
}
return cls.raw();
}
void RawClass::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
ASSERT(writer != NULL);
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
if ((kind == Snapshot::kFull) ||
(kind == Snapshot::kScript &&
!RawObject::IsCreatedFromSnapshot(writer->GetObjectTags(this)))) {
// Write out the class and tags information.
writer->WriteVMIsolateObject(kClassCid);
writer->WriteIntptrValue(writer->GetObjectTags(this));
// Write out all the non object pointer fields.
// NOTE: cpp_vtable_ is not written.
writer->WriteIntptrValue(ptr()->id_);
writer->WriteIntptrValue(ptr()->instance_size_in_words_);
writer->WriteIntptrValue(ptr()->type_arguments_field_offset_in_words_);
writer->WriteIntptrValue(ptr()->next_field_offset_in_words_);
writer->WriteIntptrValue(ptr()->num_native_fields_);
writer->WriteIntptrValue(ptr()->token_pos_);
writer->Write<uint8_t>(ptr()->state_bits_);
// Write out all the object pointer fields.
SnapshotWriterVisitor visitor(writer);
visitor.VisitPointers(from(), to());
} else {
writer->WriteClassId(this);
}
}
RawUnresolvedClass* UnresolvedClass::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
ASSERT(reader != NULL);
// Allocate unresolved class object.
UnresolvedClass& unresolved_class = UnresolvedClass::ZoneHandle(
reader->isolate(), NEW_OBJECT(UnresolvedClass));
reader->AddBackRef(object_id, &unresolved_class, kIsDeserialized);
// Set the object tags.
unresolved_class.set_tags(tags);
// Set all non object fields.
unresolved_class.set_token_pos(reader->ReadIntptrValue());
// Set all the object fields.
// TODO(5411462): Need to assert No GC can happen here, even though
// allocations may happen.
intptr_t num_flds = (unresolved_class.raw()->to() -
unresolved_class.raw()->from());
for (intptr_t i = 0; i <= num_flds; i++) {
unresolved_class.StorePointer((unresolved_class.raw()->from() + i),
reader->ReadObjectRef());
}
return unresolved_class.raw();
}
void RawUnresolvedClass::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
ASSERT(writer != NULL);
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
// Write out the class and tags information.
writer->WriteVMIsolateObject(kUnresolvedClassCid);
writer->WriteIntptrValue(writer->GetObjectTags(this));
// Write out all the non object pointer fields.
writer->WriteIntptrValue(ptr()->token_pos_);
// Write out all the object pointer fields.
SnapshotWriterVisitor visitor(writer);
visitor.VisitPointers(from(), to());
}
RawAbstractType* AbstractType::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
UNREACHABLE(); // AbstractType is an abstract class.
return NULL;
}
void RawAbstractType::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
UNREACHABLE(); // AbstractType is an abstract class.
}
RawType* Type::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
ASSERT(reader != NULL);
// Allocate type object.
Type& type = Type::ZoneHandle(reader->isolate(), NEW_OBJECT(Type));
reader->AddBackRef(object_id, &type, kIsDeserialized);
// Set all non object fields.
type.set_token_pos(reader->ReadIntptrValue());
type.set_type_state(reader->Read<int8_t>());
// Set all the object fields.
// TODO(5411462): Need to assert No GC can happen here, even though
// allocations may happen.
intptr_t num_flds = (type.raw()->to() - type.raw()->from());
for (intptr_t i = 0; i <= num_flds; i++) {
type.StorePointer((type.raw()->from() + i), reader->ReadObjectRef());
}
// If object needs to be a canonical object, Canonicalize it.
// When reading a full snapshot we don't need to canonicalize the object
// as it would already be a canonical object.
// When reading a script snapshot we need to canonicalize only those object
// references that are objects from the core library (loaded from a
// full snapshot). Objects that are only in the script need not be
// canonicalized as they are already canonical.
// When reading a message snapshot we always have to canonicalize the object.
if ((kind != Snapshot::kFull) && RawObject::IsCanonical(tags) &&
(RawObject::IsCreatedFromSnapshot(tags) ||
(kind == Snapshot::kMessage))) {
type ^= type.Canonicalize();
}
// Set the object tags (This is done after 'Canonicalize', which
// does not canonicalize a type already marked as canonical).
type.set_tags(tags);
return type.raw();
}
static const char* RawOneByteStringToCString(RawOneByteString* str) {
const char* start = reinterpret_cast<char*>(str) - kHeapObjectTag +
OneByteString::data_offset();
const int len = Smi::Value(*reinterpret_cast<RawSmi**>(
reinterpret_cast<uword>(str) - kHeapObjectTag + String::length_offset()));
char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
memmove(chars, start, len);
chars[len] = '\0';
return chars;
}
void RawType::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
ASSERT(writer != NULL);
// Only resolved and finalized types should be written to a snapshot.
// TODO(regis): Replace the test below by an ASSERT() or remove the flag test.
if (FLAG_error_on_malformed_type &&
(ptr()->type_state_ != RawType::kFinalizedInstantiated) &&
(ptr()->type_state_ != RawType::kFinalizedUninstantiated)) {
// Print the name of the class of the unfinalized type, as well as the
// token location from where it is referred to, making sure not
// to allocate any handles. Unfortunately, we cannot print the script name.
const intptr_t cid = ClassIdTag::decode(*reinterpret_cast<uword*>(
reinterpret_cast<uword>(ptr()->type_class_) - kHeapObjectTag +
Object::tags_offset()));
if (cid == kUnresolvedClassCid) {
OS::Print("Snapshotting unresolved type '%s' at token pos %"Pd"\n",
RawOneByteStringToCString(
reinterpret_cast<RawOneByteString*>(
reinterpret_cast<RawUnresolvedClass*>(
ptr()->type_class_)->ptr()->ident_)),
ptr()->token_pos_);
} else {
// Assume cid == kClassId, but it can also be kIllegalCid.
OS::Print("Snapshotting unfinalized type '%s' at token pos %"Pd"\n",
RawOneByteStringToCString(
reinterpret_cast<RawOneByteString*>(
reinterpret_cast<RawClass*>(
ptr()->type_class_)->ptr()->name_)),
ptr()->token_pos_);
}
UNREACHABLE();
}
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
// Write out the class and tags information.
writer->WriteIndexedObject(kTypeCid);
writer->WriteIntptrValue(writer->GetObjectTags(this));
// Write out all the non object pointer fields.
writer->WriteIntptrValue(ptr()->token_pos_);
writer->Write<int8_t>(ptr()->type_state_);
// Write out all the object pointer fields.
SnapshotWriterVisitor visitor(writer);
visitor.VisitPointers(from(), to());
}
RawTypeParameter* TypeParameter::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
ASSERT(reader != NULL);
// Allocate type parameter object.
TypeParameter& type_parameter = TypeParameter::ZoneHandle(
reader->isolate(), NEW_OBJECT(TypeParameter));
reader->AddBackRef(object_id, &type_parameter, kIsDeserialized);
// Set the object tags.
type_parameter.set_tags(tags);
// Set all non object fields.
type_parameter.set_index(reader->ReadIntptrValue());
type_parameter.set_token_pos(reader->ReadIntptrValue());
type_parameter.set_type_state(reader->Read<int8_t>());
// Set all the object fields.
// TODO(5411462): Need to assert No GC can happen here, even though
// allocations may happen.
intptr_t num_flds = (type_parameter.raw()->to() -
type_parameter.raw()->from());
for (intptr_t i = 0; i <= num_flds; i++) {
type_parameter.StorePointer((type_parameter.raw()->from() + i),
reader->ReadObjectRef());
}
return type_parameter.raw();
}
void RawTypeParameter::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
ASSERT(writer != NULL);
// Only finalized type parameters should be written to a snapshot.
// TODO(regis): Replace the test below by an ASSERT() or remove the flag test.
if (FLAG_error_on_malformed_type &&
(ptr()->type_state_ != RawTypeParameter::kFinalizedUninstantiated)) {
// Print the name of the unfinalized type parameter, the name of the class
// it parameterizes, as well as the token location from where it is referred
// to, making sure not to allocate any handles. Unfortunately, we cannot
// print the script name.
OS::Print("Snapshotting unfinalized type parameter '%s' of class '%s' at "
"token pos %"Pd"\n",
RawOneByteStringToCString(
reinterpret_cast<RawOneByteString*>(ptr()->name_)),
RawOneByteStringToCString(
reinterpret_cast<RawOneByteString*>(
reinterpret_cast<RawClass*>(
ptr()->parameterized_class_)->ptr()->name_)),
ptr()->token_pos_);
UNREACHABLE();
}
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
// Write out the class and tags information.
writer->WriteIndexedObject(kTypeParameterCid);
writer->WriteIntptrValue(writer->GetObjectTags(this));
// Write out all the non object pointer fields.
writer->WriteIntptrValue(ptr()->index_);
writer->WriteIntptrValue(ptr()->token_pos_);
writer->Write<int8_t>(ptr()->type_state_);
// Write out all the object pointer fields.
SnapshotWriterVisitor visitor(writer);
visitor.VisitPointers(from(), to());
}
RawBoundedType* BoundedType::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
ASSERT(reader != NULL);
// Allocate bounded type object.
BoundedType& bounded_type = BoundedType::ZoneHandle(
reader->isolate(), NEW_OBJECT(BoundedType));
reader->AddBackRef(object_id, &bounded_type, kIsDeserialized);
// Set the object tags.
bounded_type.set_tags(tags);
// Set all the object fields.
// TODO(5411462): Need to assert No GC can happen here, even though
// allocations may happen.
intptr_t num_flds = (bounded_type.raw()->to() -
bounded_type.raw()->from());
for (intptr_t i = 0; i <= num_flds; i++) {
bounded_type.StorePointer((bounded_type.raw()->from() + i),
reader->ReadObjectRef());
}
bounded_type.set_is_being_checked(false);
return bounded_type.raw();
}
void RawBoundedType::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
ASSERT(writer != NULL);
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
// Write out the class and tags information.
writer->WriteIndexedObject(kBoundedTypeCid);
writer->WriteIntptrValue(writer->GetObjectTags(this));
// Write out all the object pointer fields.
SnapshotWriterVisitor visitor(writer);
visitor.VisitPointers(from(), to());
}
RawMixinAppType* MixinAppType::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
UNREACHABLE(); // MixinAppType objects do not survive finalization.
return MixinAppType::null();
}
void RawMixinAppType::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
UNREACHABLE(); // MixinAppType objects do not survive finalization.
}
RawAbstractTypeArguments* AbstractTypeArguments::ReadFrom(
SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
UNREACHABLE(); // AbstractTypeArguments is an abstract class.
return TypeArguments::null();
}
void RawAbstractTypeArguments::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
UNREACHABLE(); // AbstractTypeArguments is an abstract class.
}
RawTypeArguments* TypeArguments::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
ASSERT(reader != NULL);
// Read the length so that we can determine instance size to allocate.
intptr_t len = reader->ReadSmiValue();
TypeArguments& type_arguments = TypeArguments::ZoneHandle(
reader->isolate(), NEW_OBJECT_WITH_LEN_SPACE(TypeArguments, len, kind));
reader->AddBackRef(object_id, &type_arguments, kIsDeserialized);
// Now set all the object fields.
for (intptr_t i = 0; i < len; i++) {
*reader->TypeHandle() ^= reader->ReadObjectImpl();
type_arguments.SetTypeAt(i, *reader->TypeHandle());
}
// If object needs to be a canonical object, Canonicalize it.
// When reading a full snapshot we don't need to canonicalize the object
// as it would already be a canonical object.
// When reading a script snapshot we need to canonicalize only those object
// references that are objects from the core library (loaded from a
// full snapshot). Objects that are only in the script need not be
// canonicalized as they are already canonical.
// When reading a message snapshot we always have to canonicalize the object.
if ((kind != Snapshot::kFull) && RawObject::IsCanonical(tags) &&
(RawObject::IsCreatedFromSnapshot(tags) ||
(kind == Snapshot::kMessage))) {
type_arguments ^= type_arguments.Canonicalize();
}
// Set the object tags (This is done after setting the object fields
// because 'SetTypeAt' has an assertion to check if the object is not
// already canonical. Also, this is done after 'Canonicalize', which
// does not canonicalize a type already marked as canonical).
type_arguments.set_tags(tags);
return type_arguments.raw();
}
void RawTypeArguments::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
ASSERT(writer != NULL);
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
// Write out the class and tags information.
writer->WriteVMIsolateObject(kTypeArgumentsCid);
writer->WriteIntptrValue(writer->GetObjectTags(this));
// Write out the length field.
writer->Write<RawObject*>(ptr()->length_);
// Write out the individual types.
intptr_t len = Smi::Value(ptr()->length_);
for (intptr_t i = 0; i < len; i++) {
writer->WriteObjectImpl(ptr()->types_[i]);
}
}
RawInstantiatedTypeArguments* InstantiatedTypeArguments::ReadFrom(
SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
ASSERT(reader != NULL);
ASSERT(kind == Snapshot::kMessage);
// Allocate instantiated types object.
InstantiatedTypeArguments& instantiated_type_arguments =
InstantiatedTypeArguments::ZoneHandle(reader->isolate(),
InstantiatedTypeArguments::New());
reader->AddBackRef(object_id, &instantiated_type_arguments, kIsDeserialized);
// Set the object tags.
instantiated_type_arguments.set_tags(tags);
// Set all the object fields.
// TODO(5411462): Need to assert No GC can happen here, even though
// allocations may happen.
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.StorePointer(
(instantiated_type_arguments.raw()->from() + i),
reader->ReadObjectRef());
}
return instantiated_type_arguments.raw();
}
void RawInstantiatedTypeArguments::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
ASSERT(writer != NULL);
ASSERT(kind == Snapshot::kMessage);
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
// Write out the class and tags information.
writer->WriteVMIsolateObject(kInstantiatedTypeArgumentsCid);
writer->WriteIntptrValue(writer->GetObjectTags(this));
// Write out all the object pointer fields.
SnapshotWriterVisitor visitor(writer);
visitor.VisitPointers(from(), to());
}
RawPatchClass* PatchClass::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
ASSERT(reader != NULL);
ASSERT((kind != Snapshot::kMessage) &&
!RawObject::IsCreatedFromSnapshot(tags));
// Allocate function object.
PatchClass& cls = PatchClass::ZoneHandle(reader->isolate(),
NEW_OBJECT(PatchClass));
reader->AddBackRef(object_id, &cls, kIsDeserialized);
// Set the object tags.
cls.set_tags(tags);
// Set all the object fields.
// TODO(5411462): Need to assert No GC can happen here, even though
// 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->ReadObjectRef();
}
return cls.raw();
}
void RawPatchClass::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
ASSERT(writer != NULL);
ASSERT((kind != Snapshot::kMessage) &&
!RawObject::IsCreatedFromSnapshot(writer->GetObjectTags(this)));
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
// Write out the class and tags information.
writer->WriteVMIsolateObject(kPatchClassCid);
writer->WriteIntptrValue(writer->GetObjectTags(this));
// Write out all the object pointer fields.
SnapshotWriterVisitor visitor(writer);
visitor.VisitPointers(from(), to());
}
RawClosureData* ClosureData::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
ASSERT(reader != NULL);
ASSERT((kind != Snapshot::kMessage) &&
!RawObject::IsCreatedFromSnapshot(tags));
// Allocate closure data object.
ClosureData& data = ClosureData::ZoneHandle(
reader->isolate(), NEW_OBJECT(ClosureData));
reader->AddBackRef(object_id, &data, kIsDeserialized);
// Set the object tags.
data.set_tags(tags);
// Set all the object fields.
// TODO(5411462): Need to assert No GC can happen here, even though
// allocations may happen.
intptr_t num_flds = (data.raw()->to() - data.raw()->from());
for (intptr_t i = 0; i <= num_flds; i++) {
*(data.raw()->from() + i) = reader->ReadObjectRef();
}
return data.raw();
}
void RawClosureData::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
ASSERT(writer != NULL);
ASSERT((kind != Snapshot::kMessage) &&
!RawObject::IsCreatedFromSnapshot(writer->GetObjectTags(this)));
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
// Write out the class and tags information.
writer->WriteVMIsolateObject(kClosureDataCid);
writer->WriteIntptrValue(writer->GetObjectTags(this));
// Context scope.
// We don't write the context scope in the snapshot.
writer->WriteObjectImpl(Object::null());
// Parent function.
writer->WriteObjectImpl(ptr()->parent_function_);
// Signature class.
writer->WriteObjectImpl(ptr()->signature_class_);
// Static closure/Closure allocation stub.
// We don't write the closure or allocation stub in the snapshot.
writer->WriteObjectImpl(Object::null());
}
RawRedirectionData* RedirectionData::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
ASSERT(reader != NULL);
ASSERT((kind != Snapshot::kMessage) &&
!RawObject::IsCreatedFromSnapshot(tags));
// Allocate redirection data object.
RedirectionData& data = RedirectionData::ZoneHandle(
reader->isolate(), NEW_OBJECT(RedirectionData));
reader->AddBackRef(object_id, &data, kIsDeserialized);
// Set the object tags.
data.set_tags(tags);
// Set all the object fields.
// TODO(5411462): Need to assert No GC can happen here, even though
// allocations may happen.
intptr_t num_flds = (data.raw()->to() - data.raw()->from());
for (intptr_t i = 0; i <= num_flds; i++) {
*(data.raw()->from() + i) = reader->ReadObjectRef();
}
return data.raw();
}
void RawRedirectionData::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
ASSERT(writer != NULL);
ASSERT((kind != Snapshot::kMessage) &&
!RawObject::IsCreatedFromSnapshot(writer->GetObjectTags(this)));
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
// Write out the class and tags information.
writer->WriteVMIsolateObject(kRedirectionDataCid);
writer->WriteIntptrValue(writer->GetObjectTags(this));
// Write out all the object pointer fields.
SnapshotWriterVisitor visitor(writer);
visitor.VisitPointers(from(), to());
}
RawFunction* Function::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
ASSERT(reader != NULL);
ASSERT((kind != Snapshot::kMessage) &&
!RawObject::IsCreatedFromSnapshot(tags));
// Allocate function object.
Function& func = Function::ZoneHandle(
reader->isolate(), NEW_OBJECT(Function));
reader->AddBackRef(object_id, &func, kIsDeserialized);
// Set the object tags.
func.set_tags(tags);
// Set all the non object fields.
func.set_token_pos(reader->ReadIntptrValue());
func.set_end_token_pos(reader->ReadIntptrValue());
func.set_usage_counter(reader->ReadIntptrValue());
func.set_num_fixed_parameters(reader->ReadIntptrValue());
func.set_num_optional_parameters(reader->ReadIntptrValue());
func.set_deoptimization_counter(reader->ReadIntptrValue());
func.set_kind_tag(reader->Read<uint16_t>());
func.set_optimized_instruction_count(reader->Read<uint16_t>());
func.set_optimized_call_site_count(reader->Read<uint16_t>());
// Set all the object fields.
// TODO(5411462): Need to assert No GC can happen here, even though
// 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->ReadObjectRef();
}
return func.raw();
}
void RawFunction::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
ASSERT(writer != NULL);
ASSERT((kind != Snapshot::kMessage) &&
!RawObject::IsCreatedFromSnapshot(writer->GetObjectTags(this)));
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
// Write out the class and tags information.
writer->WriteVMIsolateObject(kFunctionCid);
writer->WriteIntptrValue(writer->GetObjectTags(this));
// Write out all the non object fields.
writer->WriteIntptrValue(ptr()->token_pos_);
writer->WriteIntptrValue(ptr()->end_token_pos_);
writer->WriteIntptrValue(ptr()->usage_counter_);
writer->WriteIntptrValue(ptr()->num_fixed_parameters_);
writer->WriteIntptrValue(ptr()->num_optional_parameters_);
writer->WriteIntptrValue(ptr()->deoptimization_counter_);
writer->Write<uint16_t>(ptr()->kind_tag_);
writer->Write<uint16_t>(ptr()->optimized_instruction_count_);
writer->Write<uint16_t>(ptr()->optimized_call_site_count_);
// Write out all the object pointer fields.
SnapshotWriterVisitor visitor(writer);
visitor.VisitPointers(from(), to());
}
RawField* Field::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
ASSERT(reader != NULL);
ASSERT((kind != Snapshot::kMessage) &&
!RawObject::IsCreatedFromSnapshot(tags));
// Allocate field object.
Field& field = Field::ZoneHandle(reader->isolate(), NEW_OBJECT(Field));
reader->AddBackRef(object_id, &field, kIsDeserialized);
// Set the object tags.
field.set_tags(tags);
// Set all non object fields.
field.set_token_pos(reader->ReadIntptrValue());
field.set_guarded_cid(reader->ReadIntptrValue());
field.set_is_nullable(reader->ReadIntptrValue());
field.set_kind_bits(reader->Read<uint8_t>());
// Set all the object fields.
// TODO(5411462): Need to assert No GC can happen here, even though
// 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->ReadObjectRef();
}
return field.raw();
}
void RawField::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
ASSERT(writer != NULL);
ASSERT((kind != Snapshot::kMessage) &&
!RawObject::IsCreatedFromSnapshot(writer->GetObjectTags(this)));
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
// Write out the class and tags information.
writer->WriteVMIsolateObject(kFieldCid);
writer->WriteIntptrValue(writer->GetObjectTags(this));
// Write out all the non object fields.
writer->WriteIntptrValue(ptr()->token_pos_);
writer->WriteIntptrValue(ptr()->guarded_cid_);
writer->WriteIntptrValue(ptr()->is_nullable_);
writer->Write<uint8_t>(ptr()->kind_bits_);
// Write out all the object pointer fields.
SnapshotWriterVisitor visitor(writer);
visitor.VisitPointers(from(), to());
}
RawLiteralToken* LiteralToken::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
ASSERT(reader != NULL);
ASSERT(kind != Snapshot::kMessage);
// Create the literal token object.
LiteralToken& literal_token = LiteralToken::ZoneHandle(
reader->isolate(), NEW_OBJECT(LiteralToken));
reader->AddBackRef(object_id, &literal_token, kIsDeserialized);
// Set the object tags.
literal_token.set_tags(tags);
// Read the token attributes.
Token::Kind token_kind = static_cast<Token::Kind>(reader->ReadIntptrValue());
literal_token.set_kind(token_kind);
*reader->StringHandle() ^= reader->ReadObjectImpl();
literal_token.set_literal(*reader->StringHandle());
*reader->ObjectHandle() = reader->ReadObjectImpl();
literal_token.set_value(*reader->ObjectHandle());
return literal_token.raw();
}
void RawLiteralToken::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
ASSERT(writer != NULL);
ASSERT(kind != Snapshot::kMessage);
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
// Write out the class and tags information.
writer->WriteVMIsolateObject(kLiteralTokenCid);
writer->WriteIntptrValue(writer->GetObjectTags(this));
// Write out the kind field.
writer->Write<intptr_t>(ptr()->kind_);
// Write out literal and value fields.
writer->WriteObjectImpl(ptr()->literal_);
writer->WriteObjectImpl(ptr()->value_);
}
RawTokenStream* TokenStream::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
ASSERT(reader != NULL);
ASSERT((kind != Snapshot::kMessage)
&& !RawObject::IsCreatedFromSnapshot(tags));
// Read the length so that we can determine number of tokens to read.
intptr_t len = reader->ReadSmiValue();
// Create the token stream object.
TokenStream& token_stream = TokenStream::ZoneHandle(
reader->isolate(), NEW_OBJECT_WITH_LEN(TokenStream, len));
reader->AddBackRef(object_id, &token_stream, kIsDeserialized);
// Set the object tags.
token_stream.set_tags(tags);
// Read the stream of tokens into the TokenStream object for script
// snapshots as we made a copy of token stream.
if (kind == Snapshot::kScript) {
NoGCScope no_gc;
RawExternalTypedData* stream = token_stream.GetStream();
reader->ReadBytes(stream->ptr()->data_, len);
}
// Read in the literal/identifier token array.
*(reader->TokensHandle()) ^= reader->ReadObjectImpl();
token_stream.SetTokenObjects(*(reader->TokensHandle()));
// Read in the private key in use by the token stream.
*(reader->StringHandle()) ^= reader->ReadObjectImpl();
token_stream.SetPrivateKey(*(reader->StringHandle()));
return token_stream.raw();
}
void RawTokenStream::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
ASSERT(writer != NULL);
ASSERT((kind != Snapshot::kMessage) &&
!RawObject::IsCreatedFromSnapshot(writer->GetObjectTags(this)));
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
// Write out the class and tags information.
writer->WriteVMIsolateObject(kTokenStreamCid);
writer->WriteIntptrValue(writer->GetObjectTags(this));
// Write out the length field and the token stream.
RawExternalTypedData* stream = ptr()->stream_;
intptr_t len = Smi::Value(stream->ptr()->length_);
writer->Write<RawObject*>(stream->ptr()->length_);
writer->WriteBytes(stream->ptr()->data_, len);
// Write out the literal/identifier token array.
writer->WriteObjectImpl(ptr()->token_objects_);
// Write out the private key in use by the token stream.
writer->WriteObjectImpl(ptr()->private_key_);
}
RawScript* Script::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
ASSERT(reader != NULL);
ASSERT((kind != Snapshot::kMessage) &&
!RawObject::IsCreatedFromSnapshot(tags));
// Allocate script object.
Script& script = Script::ZoneHandle(reader->isolate(), NEW_OBJECT(Script));
reader->AddBackRef(object_id, &script, kIsDeserialized);
// Set the object tags.
script.set_tags(tags);
// Set all the object fields.
// TODO(5411462): Need to assert No GC can happen here, even though
// allocations may happen.
*reader->StringHandle() ^= reader->ReadObjectImpl();
script.set_url(*reader->StringHandle());
*reader->StringHandle() ^= String::null();
script.set_source(*reader->StringHandle());
TokenStream& stream = TokenStream::Handle();
stream ^= reader->ReadObjectImpl();
script.set_tokens(stream);
script.raw_ptr()->line_offset_ = reader->Read<int32_t>();
script.raw_ptr()->col_offset_ = reader->Read<int32_t>();
script.raw_ptr()->kind_ = reader->Read<int8_t>();
return script.raw();
}
void RawScript::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
ASSERT(writer != NULL);
ASSERT(tokens_ != TokenStream::null());
ASSERT((kind != Snapshot::kMessage) &&
!RawObject::IsCreatedFromSnapshot(writer->GetObjectTags(this)));
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
// Write out the class and tags information.
writer->WriteVMIsolateObject(kScriptCid);
writer->WriteIntptrValue(writer->GetObjectTags(this));
// Write out all the object pointer fields.
writer->WriteObjectImpl(ptr()->url_);
writer->WriteObjectImpl(ptr()->tokens_);
writer->Write<int32_t>(ptr()->line_offset_);
writer->Write<int32_t>(ptr()->col_offset_);
writer->Write<int8_t>(ptr()->kind_);
}
RawLibrary* Library::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
ASSERT(reader != NULL);
ASSERT(kind != Snapshot::kMessage);
Library& library = Library::ZoneHandle(reader->isolate(), Library::null());
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->ReadObjectImpl();
library = Library::LookupLibrary(*reader->StringHandle());
} else {
// Allocate library object.
library = NEW_OBJECT(Library);
// Set the object tags.
library.set_tags(tags);
// Set all non object fields.
library.raw_ptr()->index_ = reader->ReadIntptrValue();
library.raw_ptr()->num_imports_ = reader->ReadIntptrValue();
library.raw_ptr()->num_anonymous_ = reader->ReadIntptrValue();
library.raw_ptr()->corelib_imported_ = reader->Read<bool>();
library.raw_ptr()->debuggable_ = reader->Read<bool>();
library.raw_ptr()->load_state_ = reader->Read<int8_t>();
// The native resolver is not serialized.
Dart_NativeEntryResolver resolver =
reader->Read<Dart_NativeEntryResolver>();
ASSERT(resolver == NULL);
library.set_native_entry_resolver(resolver);
// The cache of loaded scripts is not serialized.
library.raw_ptr()->loaded_scripts_ = Array::null();
// Set all the object fields.
// TODO(5411462): Need to assert No GC can happen here, even though
// 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->ReadObjectRef();
}
if (kind != Snapshot::kFull) {
library.Register();
}
}
return library.raw();
}
void RawLibrary::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
ASSERT(writer != NULL);
ASSERT(kind != Snapshot::kMessage);
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
// Write out the class and tags information.
writer->WriteVMIsolateObject(kLibraryCid);
writer->WriteIntptrValue(writer->GetObjectTags(this));
if (RawObject::IsCreatedFromSnapshot(writer->GetObjectTags(this))) {
ASSERT(kind != Snapshot::kFull);
// Write out library URL so that it can be looked up when reading.
writer->WriteObjectImpl(ptr()->url_);
} else {
// Write out all non object fields.
writer->WriteIntptrValue(ptr()->index_);
writer->WriteIntptrValue(ptr()->num_imports_);
writer->WriteIntptrValue(ptr()->num_anonymous_);
writer->Write<bool>(ptr()->corelib_imported_);
writer->Write<bool>(ptr()->debuggable_);
writer->Write<int8_t>(ptr()->load_state_);
// We do not serialize the native resolver over, this needs to be explicitly
// set after deserialization.
writer->Write<Dart_NativeEntryResolver>(NULL);
// We do not write the loaded_scripts_ cache to the snapshot. It gets
// set to NULL when reading the library from the snapshot, and will
// be rebuilt lazily.
// Write out all the object pointer fields.
SnapshotWriterVisitor visitor(writer);
visitor.VisitPointers(from(), to());
}
}
RawLibraryPrefix* LibraryPrefix::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
ASSERT(reader != NULL);
ASSERT((kind != Snapshot::kMessage) &&
!RawObject::IsCreatedFromSnapshot(tags));
// Allocate library prefix object.
LibraryPrefix& prefix = LibraryPrefix::ZoneHandle(
reader->isolate(), NEW_OBJECT(LibraryPrefix));
reader->AddBackRef(object_id, &prefix, kIsDeserialized);
// Set the object tags.
prefix.set_tags(tags);
// Set all non object fields.
prefix.raw_ptr()->num_imports_ = reader->ReadIntptrValue();
// Set all the object fields.
// TODO(5411462): Need to assert No GC can happen here, even though
// 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->ReadObjectRef();
}
return prefix.raw();
}
void RawLibraryPrefix::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
ASSERT(writer != NULL);
ASSERT((kind != Snapshot::kMessage) &&
!RawObject::IsCreatedFromSnapshot(writer->GetObjectTags(this)));
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
// Write out the class and tags information.
writer->WriteVMIsolateObject(kLibraryPrefixCid);
writer->WriteIntptrValue(writer->GetObjectTags(this));
// Write out all non object fields.
writer->WriteIntptrValue(ptr()->num_imports_);
// Write out all the object pointer fields.
SnapshotWriterVisitor visitor(writer);
visitor.VisitPointers(from(), to());
}
RawNamespace* Namespace::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
ASSERT(reader != NULL);
ASSERT((kind != Snapshot::kMessage) &&
!RawObject::IsCreatedFromSnapshot(tags));
// Allocate Namespace object.
Namespace& ns = Namespace::ZoneHandle(
reader->isolate(), NEW_OBJECT(Namespace));
reader->AddBackRef(object_id, &ns, kIsDeserialized);
// Set the object tags.
ns.set_tags(tags);
// Set all the object fields.
// TODO(5411462): Need to assert No GC can happen here, even though
// allocations may happen.
intptr_t num_flds = (ns.raw()->to() - ns.raw()->from());
for (intptr_t i = 0; i <= num_flds; i++) {
*(ns.raw()->from() + i) = reader->ReadObjectRef();
}
return ns.raw();
}
void RawNamespace::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
ASSERT(writer != NULL);
ASSERT((kind != Snapshot::kMessage) &&
!RawObject::IsCreatedFromSnapshot(writer->GetObjectTags(this)));
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
// Write out the class and tags information.
writer->WriteVMIsolateObject(kNamespaceCid);
writer->WriteIntptrValue(writer->GetObjectTags(this));
// Write out all the object pointer fields.
SnapshotWriterVisitor visitor(writer);
visitor.VisitPointers(from(), to());
}
RawCode* Code::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
UNREACHABLE();
return Code::null();
}
void RawCode::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
// We have already checked for this and written a NULL object, hence we
// should not reach here.
UNREACHABLE();
}
RawInstructions* Instructions::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
UNREACHABLE();
return Instructions::null();
}
void RawInstructions::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
UNREACHABLE();
}
RawPcDescriptors* PcDescriptors::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
UNREACHABLE();
return PcDescriptors::null();
}
void RawPcDescriptors::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
UNREACHABLE();
}
RawStackmap* Stackmap::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
UNREACHABLE();
return Stackmap::null();
}
void RawStackmap::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
UNREACHABLE();
}
RawLocalVarDescriptors* LocalVarDescriptors::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
UNREACHABLE();
return LocalVarDescriptors::null();
}
void RawLocalVarDescriptors::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
UNREACHABLE();
}
RawExceptionHandlers* ExceptionHandlers::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
UNREACHABLE();
return ExceptionHandlers::null();
}
void RawExceptionHandlers::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
UNREACHABLE();
}
RawDeoptInfo* DeoptInfo::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
UNREACHABLE();
return DeoptInfo::null();
}
void RawDeoptInfo::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
UNREACHABLE();
}
RawContext* Context::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
ASSERT(reader != NULL);
// Allocate context object.
intptr_t num_vars = reader->ReadIntptrValue();
Context& context = Context::ZoneHandle(reader->isolate(), Context::null());
if (kind == Snapshot::kFull) {
context = reader->NewContext(num_vars);
} else {
context = Context::New(num_vars, HEAP_SPACE(kind));
}
reader->AddBackRef(object_id, &context, kIsDeserialized);
// Set the object tags.
context.set_tags(tags);
// Set the isolate implicitly.
context.set_isolate(Isolate::Current());
// Set all the object fields.
// TODO(5411462): Need to assert No GC can happen here, even though
// 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.StorePointer((context.raw()->from() + i), reader->ReadObjectRef());
}
return context.raw();
}
void RawContext::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
ASSERT(writer != NULL);
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
// Write out the class and tags information.
writer->WriteVMIsolateObject(kContextCid);
writer->WriteIntptrValue(writer->GetObjectTags(this));
// Write out num of variables in the context.
writer->WriteIntptrValue(ptr()->num_variables_);
// Can't serialize the isolate pointer, we set it implicitly on read.
// Write out all the object pointer fields.
SnapshotWriterVisitor visitor(writer);
visitor.VisitPointers(from(), to(ptr()->num_variables_));
}
RawContextScope* ContextScope::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
UNREACHABLE();
return NULL;
}
void RawContextScope::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
UNREACHABLE();
}
RawICData* ICData::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
UNREACHABLE();
return NULL;
}
void RawICData::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
UNREACHABLE();
}
RawMegamorphicCache* MegamorphicCache::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
UNREACHABLE();
return NULL;
}
void RawMegamorphicCache::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
UNREACHABLE();
}
RawSubtypeTestCache* SubtypeTestCache::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
UNREACHABLE();
return NULL;
}
void RawSubtypeTestCache::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
UNREACHABLE();
}
RawError* Error::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
UNREACHABLE();
return Error::null(); // Error is an abstract class.
}
void RawError::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
UNREACHABLE(); // Error is an abstract class.
}
RawApiError* ApiError::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
ASSERT(reader != NULL);
// Allocate ApiError object.
ApiError& api_error =
ApiError::ZoneHandle(reader->isolate(), NEW_OBJECT(ApiError));
reader->AddBackRef(object_id, &api_error, kIsDeserialized);
// Set the object tags.
api_error.set_tags(tags);
// Set all the object fields.
// TODO(5411462): Need to assert No GC can happen here, even though
// allocations may happen.
intptr_t num_flds = (api_error.raw()->to() - api_error.raw()->from());
for (intptr_t i = 0; i <= num_flds; i++) {
api_error.StorePointer((api_error.raw()->from() + i),
reader->ReadObjectRef());
}
return api_error.raw();
}
void RawApiError::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
ASSERT(writer != NULL);
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
// Write out the class and tags information.
writer->WriteVMIsolateObject(kApiErrorCid);
writer->WriteIntptrValue(writer->GetObjectTags(this));
// Write out all the object pointer fields.
SnapshotWriterVisitor visitor(writer);
visitor.VisitPointers(from(), to());
}
RawLanguageError* LanguageError::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
ASSERT(reader != NULL);
// Allocate LanguageError object.
LanguageError& language_error =
LanguageError::ZoneHandle(reader->isolate(), NEW_OBJECT(LanguageError));
reader->AddBackRef(object_id, &language_error, kIsDeserialized);
// Set the object tags.
language_error.set_tags(tags);
// Set all the object fields.
// TODO(5411462): Need to assert No GC can happen here, even though
// allocations may happen.
intptr_t num_flds =
(language_error.raw()->to() - language_error.raw()->from());
for (intptr_t i = 0; i <= num_flds; i++) {
language_error.StorePointer((language_error.raw()->from() + i),
reader->ReadObjectRef());
}
return language_error.raw();
}
void RawLanguageError::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
ASSERT(writer != NULL);
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
// Write out the class and tags information.
writer->WriteVMIsolateObject(kLanguageErrorCid);
writer->WriteIntptrValue(writer->GetObjectTags(this));
// Write out all the object pointer fields.
SnapshotWriterVisitor visitor(writer);
visitor.VisitPointers(from(), to());
}
RawUnhandledException* UnhandledException::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
UNREACHABLE();
return UnhandledException::null();
}
void RawUnhandledException::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
UNREACHABLE();
}
RawUnwindError* UnwindError::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
UNREACHABLE();
return UnwindError::null();
}
void RawUnwindError::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
UNREACHABLE();
}
RawInstance* Instance::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
UNREACHABLE();
return Instance::null();
}
void RawInstance::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
UNREACHABLE();
}
RawMint* Mint::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
ASSERT(reader != NULL);
// Read the 64 bit value for the object.
int64_t value = reader->Read<int64_t>();
// Create a Mint object or get canonical one if it is a canonical constant.
Mint& mint = Mint::ZoneHandle(reader->isolate(), Mint::null());
if (kind == Snapshot::kFull) {
mint = reader->NewMint(value);
} else {
// When reading a script snapshot we need to canonicalize only those object
// references that are objects from the core library (loaded from a
// full snapshot). Objects that are only in the script need not be
// canonicalized as they are already canonical.
// When reading a message snapshot we always have to canonicalize.
if (RawObject::IsCanonical(tags) &&
(RawObject::IsCreatedFromSnapshot(tags) ||
(kind == Snapshot::kMessage))) {
mint = Mint::NewCanonical(value);
} else {
mint = Mint::New(value, HEAP_SPACE(kind));
}
}
reader->AddBackRef(object_id, &mint, kIsDeserialized);
// Set the object tags.
mint.set_tags(tags);
return mint.raw();
}
void RawMint::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
ASSERT(writer != NULL);
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
// Write out the class and tags information.
writer->WriteIndexedObject(kMintCid);
writer->WriteIntptrValue(writer->GetObjectTags(this));
// Write out the 64 bit value.
writer->Write<int64_t>(ptr()->value_);
}
RawBigint* Bigint::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
ASSERT(reader != NULL);
// Read in the HexCString representation of the bigint.
intptr_t len = reader->ReadIntptrValue();
char* str = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
str[len] = '\0';
reader->ReadBytes(reinterpret_cast<uint8_t*>(str), len);
// Create a Bigint object from HexCString.
Bigint& obj = Bigint::ZoneHandle(
reader->isolate(),
((kind == Snapshot::kFull) ? reader->NewBigint(str) :
BigintOperations::FromHexCString(str, HEAP_SPACE(kind))));
// If it is a canonical constant make it one.
// When reading a full snapshot we don't need to canonicalize the object
// as it would already be a canonical object.
// When reading a script snapshot we need to canonicalize only those object
// references that are objects from the core library (loaded from a
// full snapshot). Objects that are only in the script need not be
// canonicalized as they are already canonical.
// When reading a message snapshot we always have to canonicalize the object.
if ((kind != Snapshot::kFull) && RawObject::IsCanonical(tags) &&
(RawObject::IsCreatedFromSnapshot(tags) ||
(kind == Snapshot::kMessage))) {
obj ^= obj.Canonicalize();
}
reader->AddBackRef(object_id, &obj, kIsDeserialized);
// Set the object tags.
obj.set_tags(tags);
return obj.raw();
}
void RawBigint::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
ASSERT(writer != NULL);
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
// Write out the class and tags information.
writer->WriteIndexedObject(kBigintCid);
writer->WriteIntptrValue(writer->GetObjectTags(this));
// Write out the bigint value as a HEXCstring.
intptr_t length = ptr()->signed_length_;
bool is_negative = false;
if (length <= 0) {
length = -length;
is_negative = true;
}
uword data_start = reinterpret_cast<uword>(ptr()) + sizeof(RawBigint);
const char* str = BigintOperations::ToHexCString(
length,
is_negative,
reinterpret_cast<void*>(data_start),
&BigintAllocator);
bool neg = false;
if (*str == '-') {
neg = true;
str++;
}
intptr_t len = strlen(str);
ASSERT(len > 2 && str[0] == '0' && str[1] == 'x');
if (neg) {
writer->WriteIntptrValue(len - 1); // Include '-' in length.
writer->Write<uint8_t>('-');
} else {
writer->WriteIntptrValue(len - 2);
}
writer->WriteBytes(reinterpret_cast<const uint8_t*>(&(str[2])), (len - 2));
}
RawDouble* Double::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
ASSERT(reader != NULL);
// Read the double value for the object.
double value = reader->Read<double>();
// Create a Double object or get canonical one if it is a canonical constant.
Double& dbl = Double::ZoneHandle(reader->isolate(), Double::null());
if (kind == Snapshot::kFull) {
dbl = reader->NewDouble(value);
} else {
// When reading a script snapshot we need to canonicalize only those object
// references that are objects from the core library (loaded from a
// full snapshot). Objects that are only in the script need not be
// canonicalized as they are already canonical.
// When reading a message snapshot we always have to canonicalize.
if (RawObject::IsCanonical(tags) &&
(RawObject::IsCreatedFromSnapshot(tags) ||
(kind == Snapshot::kMessage))) {
dbl = Double::NewCanonical(value);
} else {
dbl = Double::New(value, HEAP_SPACE(kind));
}
}
reader->AddBackRef(object_id, &dbl, kIsDeserialized);
// Set the object tags.
dbl.set_tags(tags);
return dbl.raw();
}
void RawDouble::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
ASSERT(writer != NULL);
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
// Write out the class and tags information.
writer->WriteIndexedObject(kDoubleCid);
writer->WriteIntptrValue(writer->GetObjectTags(this));
// Write out the double value.
writer->Write<double>(ptr()->value_);
}
RawString* String::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
UNREACHABLE(); // String is an abstract class.
return String::null();
}
void RawString::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
UNREACHABLE(); // String is an abstract class.
}
template<typename StringType, typename CharacterType, typename CallbackType>
void String::ReadFromImpl(SnapshotReader* reader,
String* str_obj,
intptr_t len,
intptr_t tags,
CallbackType new_symbol,
Snapshot::Kind kind) {
ASSERT(reader != NULL);
if (RawObject::IsCanonical(tags)) {
// Set up canonical string object.
ASSERT(reader != NULL);
CharacterType* ptr =
Isolate::Current()->current_zone()->Alloc<CharacterType>(len);
for (intptr_t i = 0; i < len; i++) {
ptr[i] = reader->Read<CharacterType>();
}
*str_obj ^= (*new_symbol)(ptr, len);
} else {
// Set up the string object.
*str_obj = StringType::New(len, HEAP_SPACE(kind));
str_obj->set_tags(tags);
str_obj->SetHash(0); // Will get computed when needed.
for (intptr_t i = 0; i < len; i++) {
*StringType::CharAddr(*str_obj, i) = reader->Read<CharacterType>();
}
}
}
RawOneByteString* OneByteString::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
// Read the length so that we can determine instance size to allocate.
ASSERT(reader != NULL);
intptr_t len = reader->ReadSmiValue();
intptr_t hash = reader->ReadSmiValue();
String& str_obj = String::Handle(reader->isolate(), String::null());
if (kind == Snapshot::kFull) {
ASSERT(reader->isolate()->no_gc_scope_depth() != 0);
RawOneByteString* obj = reader->NewOneByteString(len);
str_obj = obj;
str_obj.set_tags(tags);
obj->ptr()->hash_ = Smi::New(hash);
if (len > 0) {
uint8_t* raw_ptr = CharAddr(str_obj, 0);
reader->ReadBytes(raw_ptr, len);
}
ASSERT((hash == 0) || (String::Hash(str_obj, 0, str_obj.Length()) == hash));
} else {
String::ReadFromImpl<OneByteString, uint8_t>(
reader, &str_obj, len, tags, Symbols::FromLatin1, kind);
}
reader->AddBackRef(object_id, &str_obj, kIsDeserialized);
return raw(str_obj);
}
RawTwoByteString* TwoByteString::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
// Read the length so that we can determine instance size to allocate.
ASSERT(reader != NULL);
intptr_t len = reader->ReadSmiValue();
intptr_t hash = reader->ReadSmiValue();
String& str_obj = String::Handle(reader->isolate(), String::null());
if (kind == Snapshot::kFull) {
RawTwoByteString* obj = reader->NewTwoByteString(len);
str_obj = obj;
str_obj.set_tags(tags);
obj->ptr()->hash_ = Smi::New(hash);
uint16_t* raw_ptr = (len > 0)? CharAddr(str_obj, 0) : NULL;
for (intptr_t i = 0; i < len; i++) {
ASSERT(CharAddr(str_obj, i) == raw_ptr); // Will trigger assertions.
*raw_ptr = reader->Read<uint16_t>();
raw_ptr += 1;
}
ASSERT(String::Hash(str_obj, 0, str_obj.Length()) == hash);
} else {
String::ReadFromImpl<TwoByteString, uint16_t>(
reader, &str_obj, len, tags, Symbols::FromUTF16, kind);
}
reader->AddBackRef(object_id, &str_obj, kIsDeserialized);
return raw(str_obj);
}
template<typename T>
static void StringWriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind,
intptr_t class_id,
intptr_t tags,
RawSmi* length,
RawSmi* hash,
T* data) {
ASSERT(writer != NULL);
intptr_t len = Smi::Value(length);
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
// Write out the class and tags information.
writer->WriteIndexedObject(class_id);
writer->WriteIntptrValue(tags);
// Write out the length field.
writer->Write<RawObject*>(length);
// Write out the hash field.
writer->Write<RawObject*>(hash);
// Write out the string.
if (len > 0) {
if (class_id == kOneByteStringCid) {
writer->WriteBytes(reinterpret_cast<const uint8_t*>(data), len);
} else {
for (intptr_t i = 0; i < len; i++) {
writer->Write(data[i]);
}
}
}
}
void RawOneByteString::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
StringWriteTo(writer,
object_id,
kind,
kOneByteStringCid,
writer->GetObjectTags(this),
ptr()->length_,
ptr()->hash_,
ptr()->data_);
}
void RawTwoByteString::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
StringWriteTo(writer,
object_id,
kind,
kTwoByteStringCid,
writer->GetObjectTags(this),
ptr()->length_,
ptr()->hash_,
ptr()->data_);
}
RawExternalOneByteString* ExternalOneByteString::ReadFrom(
SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
UNREACHABLE();
return ExternalOneByteString::null();
}
RawExternalTwoByteString* ExternalTwoByteString::ReadFrom(
SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
UNREACHABLE();
return ExternalTwoByteString::null();
}
void RawExternalOneByteString::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
// Serialize as a non-external one byte string.
StringWriteTo(writer,
object_id,
kind,
kOneByteStringCid,
writer->GetObjectTags(this),
ptr()->length_,
ptr()->hash_,
ptr()->external_data_->data());
}
void RawExternalTwoByteString::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
// Serialize as a non-external two byte string.
StringWriteTo(writer,
object_id,
kind,
kTwoByteStringCid,
writer->GetObjectTags(this),
ptr()->length_,
ptr()->hash_,
ptr()->external_data_->data());
}
RawBool* Bool::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
UNREACHABLE();
return Bool::null();
}
void RawBool::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
UNREACHABLE();
}
RawArray* Array::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
ASSERT(reader != NULL);
// Read the length so that we can determine instance size to allocate.
intptr_t len = reader->ReadSmiValue();
Array* array = reinterpret_cast<Array*>(
reader->GetBackRef(object_id));
if (array == NULL) {
array = &(Array::ZoneHandle(reader->isolate(),
NEW_OBJECT_WITH_LEN_SPACE(Array, len, kind)));
reader->AddBackRef(object_id, array, kIsDeserialized);
}
reader->ArrayReadFrom(*array, len, tags);
return array->raw();
}
RawImmutableArray* ImmutableArray::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
ASSERT(reader != NULL);
// Read the length so that we can determine instance size to allocate.
intptr_t len = reader->ReadSmiValue();
ImmutableArray* array = reinterpret_cast<ImmutableArray*>(
reader->GetBackRef(object_id));
if (array == NULL) {
array = &(ImmutableArray::ZoneHandle(
reader->isolate(),
NEW_OBJECT_WITH_LEN_SPACE(ImmutableArray, len, kind)));
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) {
writer->ArrayWriteTo(object_id,
kArrayCid,
writer->GetObjectTags(this),
ptr()->length_,
ptr()->type_arguments_,
ptr()->data());
}
void RawImmutableArray::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
writer->ArrayWriteTo(object_id,
kImmutableArrayCid,
writer->GetObjectTags(this),
ptr()->length_,
ptr()->type_arguments_,
ptr()->data());
}
RawGrowableObjectArray* GrowableObjectArray::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
ASSERT(reader != NULL);
// Read the length so that we can determine instance size to allocate.
GrowableObjectArray& array = GrowableObjectArray::ZoneHandle(
reader->isolate(), GrowableObjectArray::null());
if (kind == Snapshot::kFull) {
array = reader->NewGrowableObjectArray();
} else {
array = GrowableObjectArray::New(0, HEAP_SPACE(kind));
}
reader->AddBackRef(object_id, &array, kIsDeserialized);
intptr_t length = reader->ReadSmiValue();
array.SetLength(length);
Array& contents = Array::Handle();
contents ^= reader->ReadObjectImpl();
array.SetData(contents);
const AbstractTypeArguments& type_arguments =
AbstractTypeArguments::Handle(contents.GetTypeArguments());
array.SetTypeArguments(type_arguments);
return array.raw();
}
void RawGrowableObjectArray::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
ASSERT(writer != NULL);
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
// Write out the class and tags information.
writer->WriteIndexedObject(kGrowableObjectArrayCid);
writer->WriteIntptrValue(writer->GetObjectTags(this));
// Write out the used length field.
writer->Write<RawObject*>(ptr()->length_);
// Write out the Array object.
writer->WriteObjectImpl(ptr()->data_);
}
RawFloat32x4* Float32x4::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
ASSERT(reader != NULL);
// Read the values.
float value0 = reader->Read<float>();
float value1 = reader->Read<float>();
float value2 = reader->Read<float>();
float value3 = reader->Read<float>();
// Create a Float32x4 object.
Float32x4& simd = Float32x4::ZoneHandle(reader->isolate(),
Float32x4::null());
if (kind == Snapshot::kFull) {
simd = reader->NewFloat32x4(value0, value1, value2, value3);
} else {
simd = Float32x4::New(value0, value1, value2, value3, HEAP_SPACE(kind));
}
reader->AddBackRef(object_id, &simd, kIsDeserialized);
// Set the object tags.
simd.set_tags(tags);
return simd.raw();
}
void RawFloat32x4::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
ASSERT(writer != NULL);
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
// Write out the class and tags information.
writer->WriteIndexedObject(kFloat32x4Cid);
writer->WriteIntptrValue(writer->GetObjectTags(this));
// Write out the float values.
writer->Write<float>(ptr()->value_[0]);
writer->Write<float>(ptr()->value_[1]);
writer->Write<float>(ptr()->value_[2]);
writer->Write<float>(ptr()->value_[3]);
}
RawUint32x4* Uint32x4::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
ASSERT(reader != NULL);
// Read the values.
uint32_t value0 = reader->Read<uint32_t>();
uint32_t value1 = reader->Read<uint32_t>();
uint32_t value2 = reader->Read<uint32_t>();
uint32_t value3 = reader->Read<uint32_t>();
// Create a Float32x4 object.
Uint32x4& simd = Uint32x4::ZoneHandle(reader->isolate(), Uint32x4::null());
if (kind == Snapshot::kFull) {
simd = reader->NewUint32x4(value0, value1, value2, value3);
} else {
simd = Uint32x4::New(value0, value1, value2, value3, HEAP_SPACE(kind));
}
reader->AddBackRef(object_id, &simd, kIsDeserialized);
// Set the object tags.
simd.set_tags(tags);
return simd.raw();
}
void RawUint32x4::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
ASSERT(writer != NULL);
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
// Write out the class and tags information.
writer->WriteIndexedObject(kUint32x4Cid);
writer->WriteIntptrValue(writer->GetObjectTags(this));
// Write out the mask values.
writer->Write<uint32_t>(ptr()->value_[0]);
writer->Write<uint32_t>(ptr()->value_[1]);
writer->Write<uint32_t>(ptr()->value_[2]);
writer->Write<uint32_t>(ptr()->value_[3]);
}
#define TYPED_DATA_READ(setter, type) \
for (intptr_t i = 0; i < lengthInBytes; i += element_size) { \
result.Set##setter(i, reader->Read<type>()); \
} \
RawTypedData* TypedData::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
ASSERT(reader != NULL);
intptr_t cid = RawObject::ClassIdTag::decode(tags);
intptr_t len = reader->ReadSmiValue();
TypedData& result = TypedData::ZoneHandle(
reader->isolate(), TypedData::New(cid, len, HEAP_SPACE(kind)));
reader->AddBackRef(object_id, &result, kIsDeserialized);
// Set the object tags.
result.set_tags(tags);
// Setup the array elements.
intptr_t element_size = ElementSizeInBytes(cid);
intptr_t lengthInBytes = len * element_size;
switch (cid) {
case kTypedDataInt8ArrayCid:
TYPED_DATA_READ(Int8, int8_t);
break;
case kTypedDataUint8ArrayCid:
TYPED_DATA_READ(Uint8, uint8_t);
break;
case kTypedDataUint8ClampedArrayCid:
TYPED_DATA_READ(Uint8, uint8_t);
break;
case kTypedDataInt16ArrayCid:
TYPED_DATA_READ(Int16, int16_t);
break;
case kTypedDataUint16ArrayCid:
TYPED_DATA_READ(Uint16, uint16_t);
break;
case kTypedDataInt32ArrayCid:
TYPED_DATA_READ(Int32, int32_t);
break;
case kTypedDataUint32ArrayCid:
TYPED_DATA_READ(Uint32, uint32_t);
break;
case kTypedDataInt64ArrayCid:
TYPED_DATA_READ(Int64, int64_t);
break;
case kTypedDataUint64ArrayCid:
TYPED_DATA_READ(Uint64, uint64_t);
break;
case kTypedDataFloat32ArrayCid:
TYPED_DATA_READ(Float32, float);
break;
case kTypedDataFloat64ArrayCid:
TYPED_DATA_READ(Float64, double);
break;
default:
UNREACHABLE();
}
return result.raw();
}
#undef TYPED_DATA_READ
RawExternalTypedData* ExternalTypedData::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
ASSERT(kind != Snapshot::kFull);
intptr_t cid = RawObject::ClassIdTag::decode(tags);
intptr_t length = reader->ReadSmiValue();
uint8_t* data = reinterpret_cast<uint8_t*>(reader->ReadIntptrValue());
const ExternalTypedData& obj = ExternalTypedData::Handle(
ExternalTypedData::New(cid, data, length));
void* peer = reinterpret_cast<void*>(reader->ReadIntptrValue());
Dart_WeakPersistentHandleFinalizer callback =
reinterpret_cast<Dart_WeakPersistentHandleFinalizer>(
reader->ReadIntptrValue());
obj.AddFinalizer(peer, callback);
return obj.raw();
}
#define TYPED_DATA_WRITE(type) \
{ \
type* data = reinterpret_cast<type*>(ptr()->data_); \
for (intptr_t i = 0; i < len; i++) { \
writer->Write(data[i]); \
} \
} \
void RawTypedData::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
ASSERT(writer != NULL);
intptr_t tags = writer->GetObjectTags(this);
intptr_t cid = ClassIdTag::decode(tags);
intptr_t len = Smi::Value(ptr()->length_);
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
// Write out the class and tags information.
writer->WriteIndexedObject(cid);
writer->WriteIntptrValue(tags);
// Write out the length field.
writer->Write<RawObject*>(ptr()->length_);
// Write out the array elements.
switch (cid) {
case kTypedDataInt8ArrayCid:
TYPED_DATA_WRITE(int8_t);
break;
case kTypedDataUint8ArrayCid:
TYPED_DATA_WRITE(uint8_t);
break;
case kTypedDataUint8ClampedArrayCid:
TYPED_DATA_WRITE(uint8_t);
break;
case kTypedDataInt16ArrayCid:
TYPED_DATA_WRITE(int16_t);
break;
case kTypedDataUint16ArrayCid:
TYPED_DATA_WRITE(uint16_t);
break;
case kTypedDataInt32ArrayCid:
TYPED_DATA_WRITE(int32_t);
break;
case kTypedDataUint32ArrayCid:
TYPED_DATA_WRITE(uint32_t);
break;
case kTypedDataInt64ArrayCid:
TYPED_DATA_WRITE(int64_t);
break;
case kTypedDataUint64ArrayCid:
TYPED_DATA_WRITE(uint64_t);
break;
case kTypedDataFloat32ArrayCid:
TYPED_DATA_WRITE(float); // NOLINT.
break;
case kTypedDataFloat64ArrayCid:
TYPED_DATA_WRITE(double); // NOLINT.
break;
default:
UNREACHABLE();
}
}
#define EXT_TYPED_DATA_WRITE(cid, type) \
writer->WriteIndexedObject(cid); \
writer->WriteIntptrValue(RawObject::ClassIdTag::update(cid, tags)); \
writer->Write<RawObject*>(ptr()->length_); \
TYPED_DATA_WRITE(type) \
void RawExternalTypedData::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
ASSERT(writer != NULL);
intptr_t tags = writer->GetObjectTags(this);
intptr_t cid = ClassIdTag::decode(tags);
intptr_t len = Smi::Value(ptr()->length_);
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
switch (cid) {
case kExternalTypedDataInt8ArrayCid:
EXT_TYPED_DATA_WRITE(kTypedDataInt8ArrayCid, int8_t);
break;
case kExternalTypedDataUint8ArrayCid:
EXT_TYPED_DATA_WRITE(kTypedDataUint8ArrayCid, uint8_t);
break;
case kExternalTypedDataUint8ClampedArrayCid:
EXT_TYPED_DATA_WRITE(kTypedDataUint8ClampedArrayCid, uint8_t);
break;
case kExternalTypedDataInt16ArrayCid:
EXT_TYPED_DATA_WRITE(kTypedDataInt16ArrayCid, int16_t);
break;
case kExternalTypedDataUint16ArrayCid:
EXT_TYPED_DATA_WRITE(kTypedDataUint16ArrayCid, uint16_t);
break;
case kExternalTypedDataInt32ArrayCid:
EXT_TYPED_DATA_WRITE(kTypedDataInt32ArrayCid, int32_t);
break;
case kExternalTypedDataUint32ArrayCid:
EXT_TYPED_DATA_WRITE(kTypedDataUint32ArrayCid, uint32_t);
break;
case kExternalTypedDataInt64ArrayCid:
EXT_TYPED_DATA_WRITE(kTypedDataInt64ArrayCid, int64_t);
break;
case kExternalTypedDataUint64ArrayCid:
EXT_TYPED_DATA_WRITE(kTypedDataUint64ArrayCid, uint64_t);
break;
case kExternalTypedDataFloat32ArrayCid:
EXT_TYPED_DATA_WRITE(kTypedDataFloat32ArrayCid, float); // NOLINT.
break;
case kExternalTypedDataFloat64ArrayCid:
EXT_TYPED_DATA_WRITE(kTypedDataFloat64ArrayCid, double); // NOLINT.
break;
default:
UNREACHABLE();
}
}
#undef TYPED_DATA_WRITE
#undef EXT_TYPED_DATA_WRITE
RawDartFunction* DartFunction::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
UNREACHABLE(); // DartFunction is an abstract class.
return DartFunction::null();
}
void RawDartFunction::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
UNREACHABLE(); // DartFunction is an abstract class.
}
RawStacktrace* Stacktrace::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
if (kind == Snapshot::kFull) {
Stacktrace& result = Stacktrace::ZoneHandle(reader->isolate(),
reader->NewStacktrace());
reader->AddBackRef(object_id, &result, kIsDeserialized);
// There are no non object pointer fields.
// Read all the object pointer fields.
Array& array = Array::Handle(reader->isolate());
array ^= reader->ReadObjectRef();
result.set_function_array(array);
array ^= reader->ReadObjectRef();
result.set_code_array(array);
array ^= reader->ReadObjectRef();
result.set_pc_offset_array(array);
array ^= reader->ReadObjectRef();
result.set_catch_func_array(array);
array ^= reader->ReadObjectRef();
result.set_catch_code_array(array);
array ^= reader->ReadObjectRef();
result.set_catch_pc_offset_array(array);
return result.raw();
}
UNREACHABLE(); // Stacktraces are not sent in a snapshot.
return Stacktrace::null();
}
void RawStacktrace::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
if (kind == Snapshot::kFull) {
ASSERT(writer != NULL);
ASSERT(this == Isolate::Current()->object_store()->
preallocated_stack_trace());
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
// Write out the class and tags information.
writer->WriteIndexedObject(kStacktraceCid);
writer->WriteIntptrValue(writer->GetObjectTags(this));
// There are no non object pointer fields.
// Write out all the object pointer fields.
SnapshotWriterVisitor visitor(writer);
visitor.VisitPointers(from(), to());
} else {
// Stacktraces are not allowed in other snapshot forms.
writer->SetWriteException(Exceptions::kArgument,
"Illegal argument in isolate message"
" : (object is a stacktrace)");
}
}
RawJSRegExp* JSRegExp::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
ASSERT(reader != NULL);
ASSERT(kind == Snapshot::kMessage);
// Read the length so that we can determine instance size to allocate.
intptr_t len = reader->ReadSmiValue();
// Allocate JSRegExp object.
JSRegExp& regex = JSRegExp::ZoneHandle(
reader->isolate(), JSRegExp::New(len, HEAP_SPACE(kind)));
reader->AddBackRef(object_id, &regex, 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->ReadObjectImpl();
regex.set_pattern(*reader->StringHandle());
regex.raw_ptr()->type_ = reader->ReadIntptrValue();
regex.raw_ptr()->flags_ = reader->ReadIntptrValue();
// TODO(5411462): Need to implement a way of recompiling the regex.
return regex.raw();
}
void RawJSRegExp::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
ASSERT(writer != NULL);
ASSERT(kind == Snapshot::kMessage);
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
// Write out the class and tags information.
writer->WriteIndexedObject(kJSRegExpCid);
writer->WriteIntptrValue(writer->GetObjectTags(this));
// Write out the data length field.
writer->Write<RawObject*>(ptr()->data_length_);
// Write out all the other fields.
writer->Write<RawObject*>(ptr()->num_bracket_expressions_);
writer->WriteObjectImpl(ptr()->pattern_);
writer->WriteIntptrValue(ptr()->type_);
writer->WriteIntptrValue(ptr()->flags_);
// Do not write out the data part which is native.
}
RawWeakProperty* WeakProperty::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
ASSERT(reader != NULL);
// Allocate the weak property object.
WeakProperty& weak_property = WeakProperty::ZoneHandle(
reader->isolate(), WeakProperty::New(HEAP_SPACE(kind)));
reader->AddBackRef(object_id, &weak_property, kIsDeserialized);
// Set the object tags.
weak_property.set_tags(tags);
// Set all the object fields.
weak_property.raw_ptr()->key_ = reader->ReadObjectRef();
weak_property.raw_ptr()->value_ = reader->ReadObjectRef();
return weak_property.raw();
}
void RawWeakProperty::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
ASSERT(writer != NULL);
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
// Write out the class and tags information.
writer->WriteIndexedObject(kWeakPropertyCid);
writer->WriteIntptrValue(writer->GetObjectTags(this));
// Write out all the other fields.
writer->Write<RawObject*>(ptr()->key_);
writer->Write<RawObject*>(ptr()->value_);
}
} // namespace dart