Index: vm/snapshot.cc |
=================================================================== |
--- vm/snapshot.cc (revision 14907) |
+++ vm/snapshot.cc (working copy) |
@@ -9,6 +9,7 @@ |
#include "vm/bootstrap.h" |
#include "vm/exceptions.h" |
#include "vm/heap.h" |
+#include "vm/longjump.h" |
#include "vm/object.h" |
#include "vm/object_store.h" |
#include "vm/snapshot_ids.h" |
@@ -740,6 +741,21 @@ |
} |
+SnapshotWriter::SnapshotWriter(Snapshot::Kind kind, |
+ uint8_t** buffer, |
+ ReAlloc alloc, |
+ intptr_t increment_size) |
+ : BaseWriter(buffer, alloc, increment_size), |
+ kind_(kind), |
+ object_store_(Isolate::Current()->object_store()), |
+ class_table_(Isolate::Current()->class_table()), |
+ forward_list_(), |
+ exception_type_(Exceptions::kNone), |
+ exception_msg_(NULL), |
+ error_(LanguageError::Handle()) { |
+} |
+ |
+ |
void SnapshotWriter::WriteObject(RawObject* rawobj) { |
WriteObjectImpl(rawobj); |
WriteForwardedObjects(); |
@@ -800,7 +816,14 @@ |
intptr_t class_id = cls->ptr()->id_; |
ASSERT(class_id == raw->GetClassId()); |
if (class_id >= kNumPredefinedCids) { |
- ASSERT(!Class::IsSignatureClass(cls)); |
+ if (Class::IsSignatureClass(cls)) { |
+ // We do not allow closure objects in an isolate message. |
+ set_exception_type(Exceptions::kArgumentError); |
+ // TODO(asiva): Allocate these constant strings once in the VM isolate. |
+ set_exception_msg("Illegal argument in isolate message" |
+ " : (object is a closure)"); |
+ Isolate::Current()->long_jump_base()->Jump(1, *ErrorHandle()); |
+ } |
// 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 |
@@ -885,19 +908,36 @@ |
ObjectStore* object_store = isolate->object_store(); |
ASSERT(object_store != NULL); |
- // Reserve space in the output buffer for a snapshot header. |
- ReserveHeader(); |
+ // Setup for long jump in case there is an exception while writing |
+ // the snapshot. |
+ LongJump* base = isolate->long_jump_base(); |
+ LongJump jump; |
+ isolate->set_long_jump_base(&jump); |
+ // TODO(asiva): Allocate these constant strings once in the VM isolate. |
+ *ErrorHandle() = LanguageError::New( |
+ String::Handle(String::New("Error while writing full snapshot"))); |
+ if (setjmp(*jump.Set()) == 0) { |
+ NoGCScope no_gc; |
- // 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, false); |
- object_store->VisitObjectPointers(&visitor); |
+ // Reserve space in the output buffer for a snapshot header. |
+ ReserveHeader(); |
- // Write out all forwarded objects. |
- WriteForwardedObjects(); |
+ // 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, false); |
+ object_store->VisitObjectPointers(&visitor); |
- FillHeader(kind()); |
- UnmarkAll(); |
+ // Write out all forwarded objects. |
+ WriteForwardedObjects(); |
+ |
+ FillHeader(kind()); |
+ UnmarkAll(); |
+ |
+ isolate->set_long_jump_base(base); |
+ } else { |
+ isolate->set_long_jump_base(base); |
+ ThrowException(exception_type(), exception_msg()); |
+ } |
} |
@@ -1031,11 +1071,24 @@ |
intptr_t class_id = cls->ptr()->id_; |
if (class_id >= kNumPredefinedCids) { |
- ASSERT(!Class::IsSignatureClass(cls)); |
+ if (Class::IsSignatureClass(cls)) { |
+ // We do not allow closure objects in an isolate message. |
+ set_exception_type(Exceptions::kArgumentError); |
+ // TODO(asiva): Allocate these constant strings once in the VM isolate. |
+ set_exception_msg("Illegal argument in isolate message" |
+ " : (object is a closure)"); |
+ Isolate::Current()->long_jump_base()->Jump(1, *ErrorHandle()); |
+ } |
+ if (cls->ptr()->num_native_fields_ != 0) { |
+ // We do not allow objects with native fields in an isolate message. |
+ set_exception_type(Exceptions::kArgumentError); |
+ // TODO(asiva): Allocate these constant strings once in the VM isolate. |
+ set_exception_msg("Illegal argument in isolate message" |
+ " : (object extends NativeWrapper)"); |
+ |
+ Isolate::Current()->long_jump_base()->Jump(1, *ErrorHandle()); |
+ } |
// Object is regular dart instance. |
- // TODO(5411462): figure out what we need to do if an object with native |
- // fields is serialized (throw exception or serialize a null object). |
- ASSERT(cls->ptr()->num_native_fields_ == 0); |
intptr_t instance_size = cls->ptr()->instance_size_; |
ASSERT(instance_size != 0); |
@@ -1148,14 +1201,42 @@ |
} |
+void SnapshotWriter::ThrowException(Exceptions::ExceptionType type, |
+ const char* msg) { |
+ Isolate::Current()->object_store()->clear_sticky_error(); |
+ UnmarkAll(); |
+ const String& msg_obj = String::Handle(String::New(msg)); |
+ GrowableArray<const Object*> args(1); |
+ args.Add(&msg_obj); |
+ Exceptions::ThrowByType(type, args); |
+ UNREACHABLE(); |
+} |
+ |
+ |
void ScriptSnapshotWriter::WriteScriptSnapshot(const Library& lib) { |
ASSERT(kind() == Snapshot::kScript); |
+ Isolate* isolate = Isolate::Current(); |
+ ASSERT(isolate != NULL); |
- // Write out the library object. |
- ReserveHeader(); |
- WriteObject(lib.raw()); |
- FillHeader(kind()); |
- UnmarkAll(); |
+ // Setup for long jump in case there is an exception while writing |
+ // the snapshot. |
+ LongJump* base = isolate->long_jump_base(); |
+ LongJump jump; |
+ isolate->set_long_jump_base(&jump); |
+ *ErrorHandle() = LanguageError::New( |
+ String::Handle(String::New("Error while writing script snapshot"))); |
+ if (setjmp(*jump.Set()) == 0) { |
+ // Write out the library object. |
+ NoGCScope no_gc; |
+ ReserveHeader(); |
+ WriteObject(lib.raw()); |
+ FillHeader(kind()); |
+ UnmarkAll(); |
+ isolate->set_long_jump_base(base); |
+ } else { |
+ isolate->set_long_jump_base(base); |
+ ThrowException(exception_type(), exception_msg()); |
+ } |
} |
@@ -1173,8 +1254,25 @@ |
void MessageWriter::WriteMessage(const Object& obj) { |
ASSERT(kind() == Snapshot::kMessage); |
- WriteObject(obj.raw()); |
- UnmarkAll(); |
+ Isolate* isolate = Isolate::Current(); |
+ ASSERT(isolate != NULL); |
+ |
+ // Setup for long jump in case there is an exception while writing |
+ // the message. |
+ LongJump* base = isolate->long_jump_base(); |
+ LongJump jump; |
+ isolate->set_long_jump_base(&jump); |
+ *ErrorHandle() = LanguageError::New( |
+ String::Handle(String::New("Error while writing message"))); |
+ if (setjmp(*jump.Set()) == 0) { |
+ NoGCScope no_gc; |
+ WriteObject(obj.raw()); |
+ UnmarkAll(); |
+ isolate->set_long_jump_base(base); |
+ } else { |
+ isolate->set_long_jump_base(base); |
+ ThrowException(exception_type(), exception_msg()); |
+ } |
} |