| Index: runtime/vm/snapshot.cc
|
| ===================================================================
|
| --- runtime/vm/snapshot.cc (revision 44266)
|
| +++ runtime/vm/snapshot.cc (working copy)
|
| @@ -237,6 +237,46 @@
|
| }
|
|
|
|
|
| +RawObject* SnapshotReader::ReadStaticImplicitClosure(intptr_t object_id,
|
| + intptr_t class_header) {
|
| + ASSERT(kind_ == Snapshot::kMessage);
|
| +
|
| + // First create a function object and associate it with the specified
|
| + // 'object_id'.
|
| + Function& func = Function::ZoneHandle(isolate(), Function::null());
|
| + AddBackRef(object_id, &func, kIsDeserialized);
|
| +
|
| + // Read the library/class/function information and lookup the function.
|
| + str_ ^= ReadObjectImpl();
|
| + library_ = Library::LookupLibrary(str_);
|
| + if (library_.IsNull() || !library_.Loaded()) {
|
| + SetReadException("Invalid Library object found in message.");
|
| + }
|
| + str_ ^= ReadObjectImpl();
|
| + if (str_.Equals(Symbols::TopLevel())) {
|
| + str_ ^= ReadObjectImpl();
|
| + func = library_.LookupFunctionAllowPrivate(str_);
|
| + } else {
|
| + cls_ = library_.LookupClassAllowPrivate(str_);
|
| + if (cls_.IsNull()) {
|
| + OS::Print("Name of class not found %s\n", str_.ToCString());
|
| + SetReadException("Invalid Class object found in message.");
|
| + }
|
| + cls_.EnsureIsFinalized(isolate());
|
| + str_ ^= ReadObjectImpl();
|
| + func = cls_.LookupFunctionAllowPrivate(str_);
|
| + }
|
| + if (func.IsNull()) {
|
| + SetReadException("Invalid function object found in message.");
|
| + }
|
| + func = func.ImplicitClosureFunction();
|
| + ASSERT(!func.IsNull());
|
| +
|
| + // Return the associated implicit static closure.
|
| + return func.ImplicitStaticClosure();
|
| +}
|
| +
|
| +
|
| RawObject* SnapshotReader::ReadObjectImpl() {
|
| int64_t value = Read<int64_t>();
|
| if ((value & kSmiTagMask) == kSmiTag) {
|
| @@ -312,7 +352,8 @@
|
| // 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) == kInstanceObjectId) {
|
| + intptr_t header_id = SerializedHeaderData::decode(class_header);
|
| + if (header_id == kInstanceObjectId) {
|
| Instance& result = Instance::ZoneHandle(isolate(), Instance::null());
|
| AddBackRef(object_id, &result, kIsNotDeserialized);
|
|
|
| @@ -326,6 +367,12 @@
|
| result ^= Object::Allocate(cls_.id(), instance_size, HEAP_SPACE(kind_));
|
| }
|
| return result.raw();
|
| + } else if (header_id == kStaticImplicitClosureObjectId) {
|
| + // We skip the tags that have been written as the implicit static
|
| + // closure is going to be created in this isolate or the canonical
|
| + // version already created in the isolate will be used.
|
| + ReadTags();
|
| + return ReadStaticImplicitClosure(object_id, class_header);
|
| }
|
| ASSERT((class_header & kSmiTagMask) != kSmiTag);
|
|
|
| @@ -937,7 +984,8 @@
|
| // Read the class header information and lookup the class.
|
| intptr_t class_header = Read<int32_t>();
|
| intptr_t tags = ReadTags();
|
| - if (SerializedHeaderData::decode(class_header) == kInstanceObjectId) {
|
| + intptr_t header_id = SerializedHeaderData::decode(class_header);
|
| + if (header_id == kInstanceObjectId) {
|
| // Object is regular dart instance.
|
| Instance* result = reinterpret_cast<Instance*>(GetBackRef(object_id));
|
| intptr_t instance_size = 0;
|
| @@ -1002,6 +1050,11 @@
|
| ASSERT(!result->IsNull());
|
| }
|
| return result->raw();
|
| + } else if (header_id == kStaticImplicitClosureObjectId) {
|
| + // We do not use the tags as the implicit static closure
|
| + // is going to be created in this isolate or the canonical
|
| + // version already created in the isolate will be used.
|
| + return ReadStaticImplicitClosure(object_id, class_header);
|
| }
|
| ASSERT((class_header & kSmiTagMask) != kSmiTag);
|
| intptr_t class_id = LookupInternalClass(class_header);
|
| @@ -1215,10 +1268,10 @@
|
| WriteInstanceRef(raw, cls);
|
| 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.
|
| + // Add object 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 having
|
| + // been serialized so that we do not serialize the object when we go through
|
| + // the forward list.
|
| forward_list_.MarkAndAddObject(raw, kIsSerialized);
|
| switch (class_id) {
|
| #define SNAPSHOT_WRITE(clazz) \
|
| @@ -1592,6 +1645,29 @@
|
| }
|
|
|
|
|
| +void SnapshotWriter::WriteStaticImplicitClosure(intptr_t object_id,
|
| + RawFunction* func,
|
| + intptr_t tags) {
|
| + // Write out the serialization header value for this object.
|
| + WriteInlinedObjectHeader(object_id);
|
| +
|
| + // Indicate this is a static implicit closure object.
|
| + Write<int32_t>(SerializedHeaderData::encode(kStaticImplicitClosureObjectId));
|
| +
|
| + // Write out the tags.
|
| + WriteTags(tags);
|
| +
|
| + // Write out the library url, class name and signature function name.
|
| + RawClass* cls = GetFunctionOwner(func);
|
| + ASSERT(cls != Class::null());
|
| + RawLibrary* library = cls->ptr()->library_;
|
| + ASSERT(library != Library::null());
|
| + WriteObjectImpl(library->ptr()->url_);
|
| + WriteObjectImpl(cls->ptr()->name_);
|
| + WriteObjectImpl(func->ptr()->name_);
|
| +}
|
| +
|
| +
|
| void SnapshotWriter::ArrayWriteTo(intptr_t object_id,
|
| intptr_t array_kind,
|
| intptr_t tags,
|
| @@ -1625,34 +1701,63 @@
|
| }
|
|
|
|
|
| -void SnapshotWriter::CheckIfSerializable(RawClass* cls) {
|
| +RawFunction* SnapshotWriter::IsSerializableClosure(RawClass* cls,
|
| + RawObject* obj) {
|
| if (Class::IsSignatureClass(cls)) {
|
| - // We do not allow closure objects in an isolate message.
|
| - Isolate* isolate = Isolate::Current();
|
| - HANDLESCOPE(isolate);
|
| + // 'obj' is a closure as its class is a signature class, extract
|
| + // the function object to check if this closure can be sent in an
|
| + // isolate message.
|
| + RawFunction* func = Closure::GetFunction(obj);
|
| + // We only allow closure of top level methods or static functions in a
|
| + // class to be sent in isolate messages.
|
| + if (can_send_any_object() &&
|
| + Function::IsImplicitStaticClosureFunction(func)) {
|
| + return func;
|
| + }
|
| + // Not a closure of a top level method or static function, throw an
|
| + // exception as we do not allow these objects to be serialized.
|
| + HANDLESCOPE(isolate());
|
| +
|
| + const Class& clazz = Class::Handle(isolate(), cls);
|
| + const Function& errorFunc = Function::Handle(isolate(), func);
|
| + ASSERT(!errorFunc.IsNull());
|
| +
|
| + // All other closures are errors.
|
| const char* format = "Illegal argument in isolate message"
|
| - " : (object is a closure - %s %s)";
|
| + " : (object is a closure - %s %s)";
|
| UnmarkAll(); // Unmark objects now as we are about to print stuff.
|
| - const Class& clazz = Class::Handle(isolate, cls);
|
| - const Function& func = Function::Handle(isolate,
|
| - clazz.signature_function());
|
| - ASSERT(!func.IsNull());
|
| intptr_t len = OS::SNPrint(NULL, 0, format,
|
| - clazz.ToCString(), func.ToCString()) + 1;
|
| - char* chars = isolate->current_zone()->Alloc<char>(len);
|
| - OS::SNPrint(chars, len, format, clazz.ToCString(), func.ToCString());
|
| + clazz.ToCString(), errorFunc.ToCString()) + 1;
|
| + char* chars = isolate()->current_zone()->Alloc<char>(len);
|
| + OS::SNPrint(chars, len, format, clazz.ToCString(), errorFunc.ToCString());
|
| SetWriteException(Exceptions::kArgument, chars);
|
| }
|
| + return Function::null();
|
| +}
|
| +
|
| +
|
| +RawClass* SnapshotWriter::GetFunctionOwner(RawFunction* func) {
|
| + RawObject* owner = func->ptr()->owner_;
|
| + uword tags = GetObjectTags(owner);
|
| + intptr_t class_id = RawObject::ClassIdTag::decode(tags);
|
| + if (class_id == kClassCid) {
|
| + return reinterpret_cast<RawClass*>(owner);
|
| + }
|
| + ASSERT(class_id == kPatchClassCid);
|
| + return reinterpret_cast<RawPatchClass*>(owner)->ptr()->patched_class_;
|
| +}
|
| +
|
| +
|
| +void SnapshotWriter::CheckForNativeFields(RawClass* cls) {
|
| if (cls->ptr()->num_native_fields_ != 0) {
|
| // We do not allow objects with native fields in an isolate message.
|
| - Isolate* isolate = Isolate::Current();
|
| - HANDLESCOPE(Isolate::Current());
|
| + HANDLESCOPE(isolate());
|
| const char* format = "Illegal argument in isolate message"
|
| " : (object extends NativeWrapper - %s)";
|
| UnmarkAll(); // Unmark objects now as we are about to print stuff.
|
| - const Class& clazz = Class::Handle(isolate, cls);
|
| + const Class& clazz = Class::Handle(isolate(), cls);
|
| intptr_t len = OS::SNPrint(NULL, 0, format, clazz.ToCString()) + 1;
|
| - char* chars = isolate->current_zone()->Alloc<char>(len);
|
| + char* chars = isolate()->current_zone()->Alloc<char>(len);
|
| OS::SNPrint(chars, len, format, clazz.ToCString());
|
| SetWriteException(Exceptions::kArgument, chars);
|
| }
|
| @@ -1673,11 +1778,20 @@
|
| RawObject* raw,
|
| RawClass* cls,
|
| intptr_t tags) {
|
| - // First check if object is a closure or has native fields.
|
| - CheckIfSerializable(cls);
|
| + // Check if the instance has native fields and throw an exception if it does.
|
| + CheckForNativeFields(cls);
|
|
|
| + // Check if object is a closure that is serializable, if the object is a
|
| + // closure that is not serializable this will throw an exception.
|
| + RawFunction* func = IsSerializableClosure(cls, raw);
|
| + if (func != Function::null()) {
|
| + WriteStaticImplicitClosure(object_id, func, tags);
|
| + return;
|
| + }
|
| +
|
| // Object is regular dart instance.
|
| - intptr_t next_field_offset =
|
| + intptr_t next_field_offset = Class::IsSignatureClass(cls) ?
|
| + Closure::InstanceSize() :
|
| cls->ptr()->next_field_offset_in_words_ << kWordSizeLog2;
|
| ASSERT(next_field_offset > 0);
|
|
|
| @@ -1713,9 +1827,26 @@
|
|
|
|
|
| void SnapshotWriter::WriteInstanceRef(RawObject* raw, RawClass* cls) {
|
| - // First check if object is a closure or has native fields.
|
| - CheckIfSerializable(cls);
|
| + // Check if the instance has native fields and throw an exception if it does.
|
| + CheckForNativeFields(cls);
|
|
|
| + // Check if object is a closure that is serializable, if the object is a
|
| + // closure that is not serializable this will throw an exception.
|
| + RawFunction* func = IsSerializableClosure(cls, raw);
|
| + if (func != Function::null()) {
|
| + // Add object 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 having
|
| + // been serialized so that we do not serialize the object when we go through
|
| + // the forward list.
|
| + forward_list_.MarkAndAddObject(raw, kIsSerialized);
|
| + uword tags = raw->ptr()->tags_;
|
| + ASSERT(SerializedHeaderTag::decode(tags) == kObjectId);
|
| + intptr_t object_id = SerializedHeaderData::decode(tags);
|
| + tags = forward_list_.NodeForObjectId(object_id)->tags();
|
| + WriteStaticImplicitClosure(object_id, func, tags);
|
| + 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
|
|
|