OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/snapshot.h" | 5 #include "vm/snapshot.h" |
6 | 6 |
7 #include "platform/assert.h" | 7 #include "platform/assert.h" |
8 #include "vm/bootstrap.h" | 8 #include "vm/bootstrap.h" |
9 #include "vm/class_finalizer.h" | 9 #include "vm/class_finalizer.h" |
10 #include "vm/dart.h" | 10 #include "vm/dart.h" |
11 #include "vm/dart_entry.h" | 11 #include "vm/dart_entry.h" |
12 #include "vm/exceptions.h" | 12 #include "vm/exceptions.h" |
13 #include "vm/heap.h" | 13 #include "vm/heap.h" |
14 #include "vm/lockers.h" | 14 #include "vm/lockers.h" |
15 #include "vm/longjump.h" | 15 #include "vm/longjump.h" |
16 #include "vm/object.h" | 16 #include "vm/object.h" |
17 #include "vm/object_store.h" | 17 #include "vm/object_store.h" |
18 #include "vm/snapshot_ids.h" | 18 #include "vm/snapshot_ids.h" |
| 19 #include "vm/stub_code.h" |
19 #include "vm/symbols.h" | 20 #include "vm/symbols.h" |
20 #include "vm/verified_memory.h" | 21 #include "vm/verified_memory.h" |
21 #include "vm/version.h" | 22 #include "vm/version.h" |
22 | 23 |
23 // We currently only expect the Dart mutator to read snapshots. | 24 // We currently only expect the Dart mutator to read snapshots. |
24 #define ASSERT_NO_SAFEPOINT_SCOPE() \ | 25 #define ASSERT_NO_SAFEPOINT_SCOPE() \ |
25 isolate()->AssertCurrentThreadIsMutator(); \ | 26 isolate()->AssertCurrentThreadIsMutator(); \ |
26 ASSERT(thread()->no_safepoint_scope_depth() != 0) | 27 ASSERT(thread()->no_safepoint_scope_depth() != 0) |
27 | 28 |
28 namespace dart { | 29 namespace dart { |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
164 | 165 |
165 | 166 |
166 intptr_t BaseReader::ReadSmiValue() { | 167 intptr_t BaseReader::ReadSmiValue() { |
167 return Smi::Value(ReadAsSmi()); | 168 return Smi::Value(ReadAsSmi()); |
168 } | 169 } |
169 | 170 |
170 | 171 |
171 SnapshotReader::SnapshotReader( | 172 SnapshotReader::SnapshotReader( |
172 const uint8_t* buffer, | 173 const uint8_t* buffer, |
173 intptr_t size, | 174 intptr_t size, |
| 175 const uint8_t* instructions_buffer, |
174 Snapshot::Kind kind, | 176 Snapshot::Kind kind, |
175 ZoneGrowableArray<BackRefNode>* backward_refs, | 177 ZoneGrowableArray<BackRefNode>* backward_refs, |
176 Thread* thread) | 178 Thread* thread) |
177 : BaseReader(buffer, size), | 179 : BaseReader(buffer, size), |
| 180 instructions_buffer_(instructions_buffer), |
178 kind_(kind), | 181 kind_(kind), |
179 snapshot_code_(false), | 182 snapshot_code_(instructions_buffer != NULL), |
180 thread_(thread), | 183 thread_(thread), |
181 zone_(thread->zone()), | 184 zone_(thread->zone()), |
182 heap_(isolate()->heap()), | 185 heap_(isolate()->heap()), |
183 old_space_(thread_->isolate()->heap()->old_space()), | 186 old_space_(thread_->isolate()->heap()->old_space()), |
184 cls_(Class::Handle(zone_)), | 187 cls_(Class::Handle(zone_)), |
185 obj_(Object::Handle(zone_)), | 188 obj_(Object::Handle(zone_)), |
186 pobj_(PassiveObject::Handle(zone_)), | 189 pobj_(PassiveObject::Handle(zone_)), |
187 array_(Array::Handle(zone_)), | 190 array_(Array::Handle(zone_)), |
188 field_(Field::Handle(zone_)), | 191 field_(Field::Handle(zone_)), |
189 str_(String::Handle(zone_)), | 192 str_(String::Handle(zone_)), |
190 library_(Library::Handle(zone_)), | 193 library_(Library::Handle(zone_)), |
191 type_(AbstractType::Handle(zone_)), | 194 type_(AbstractType::Handle(zone_)), |
192 type_arguments_(TypeArguments::Handle(zone_)), | 195 type_arguments_(TypeArguments::Handle(zone_)), |
193 tokens_(Array::Handle(zone_)), | 196 tokens_(Array::Handle(zone_)), |
194 stream_(TokenStream::Handle(zone_)), | 197 stream_(TokenStream::Handle(zone_)), |
195 data_(ExternalTypedData::Handle(zone_)), | 198 data_(ExternalTypedData::Handle(zone_)), |
196 typed_data_(TypedData::Handle(zone_)), | 199 typed_data_(TypedData::Handle(zone_)), |
| 200 code_(Code::Handle(zone_)), |
197 error_(UnhandledException::Handle(zone_)), | 201 error_(UnhandledException::Handle(zone_)), |
198 max_vm_isolate_object_id_( | 202 max_vm_isolate_object_id_( |
199 (kind == Snapshot::kFull) ? | 203 (kind == Snapshot::kFull) ? |
200 Object::vm_isolate_snapshot_object_table().Length() : 0), | 204 Object::vm_isolate_snapshot_object_table().Length() : 0), |
201 backward_references_(backward_refs) { | 205 backward_references_(backward_refs), |
| 206 instructions_reader_(NULL) { |
| 207 if (instructions_buffer != NULL) { |
| 208 instructions_reader_ = new InstructionsReader(instructions_buffer); |
| 209 } |
202 } | 210 } |
203 | 211 |
204 | 212 |
205 RawObject* SnapshotReader::ReadObject() { | 213 RawObject* SnapshotReader::ReadObject() { |
206 // Setup for long jump in case there is an exception while reading. | 214 // Setup for long jump in case there is an exception while reading. |
207 LongJumpScope jump; | 215 LongJumpScope jump; |
208 if (setjmp(*jump.Set()) == 0) { | 216 if (setjmp(*jump.Set()) == 0) { |
209 PassiveObject& obj = | 217 PassiveObject& obj = |
210 PassiveObject::Handle(isolate(), ReadObjectImpl(kAsInlinedObject)); | 218 PassiveObject::Handle(isolate(), ReadObjectImpl(kAsInlinedObject)); |
211 for (intptr_t i = 0; i < backward_references_->length(); i++) { | 219 for (intptr_t i = 0; i < backward_references_->length(); i++) { |
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
495 } else { | 503 } else { |
496 *result ^= Object::Allocate(cls_.id(), | 504 *result ^= Object::Allocate(cls_.id(), |
497 instance_size, | 505 instance_size, |
498 HEAP_SPACE(kind_)); | 506 HEAP_SPACE(kind_)); |
499 } | 507 } |
500 } else { | 508 } else { |
501 cls_ ^= ReadObjectImpl(kAsInlinedObject); | 509 cls_ ^= ReadObjectImpl(kAsInlinedObject); |
502 ASSERT(!cls_.IsNull()); | 510 ASSERT(!cls_.IsNull()); |
503 instance_size = cls_.instance_size(); | 511 instance_size = cls_.instance_size(); |
504 } | 512 } |
505 intptr_t next_field_offset = cls_.next_field_offset(); | 513 intptr_t next_field_offset = Class::IsSignatureClass(cls_.raw()) |
| 514 ? Closure::InstanceSize() : cls_.next_field_offset(); |
| 515 |
506 intptr_t type_argument_field_offset = cls_.type_arguments_field_offset(); | 516 intptr_t type_argument_field_offset = cls_.type_arguments_field_offset(); |
507 ASSERT(next_field_offset > 0); | 517 ASSERT(next_field_offset > 0); |
508 // Instance::NextFieldOffset() returns the offset of the first field in | 518 // Instance::NextFieldOffset() returns the offset of the first field in |
509 // a Dart object. | 519 // a Dart object. |
510 bool as_reference = RawObject::IsCanonical(tags) ? false : true; | 520 bool as_reference = RawObject::IsCanonical(tags) ? false : true; |
511 intptr_t offset = Instance::NextFieldOffset(); | 521 intptr_t offset = Instance::NextFieldOffset(); |
512 intptr_t result_cid = result->GetClassId(); | 522 intptr_t result_cid = result->GetClassId(); |
513 while (offset < next_field_offset) { | 523 while (offset < next_field_offset) { |
514 pobj_ = ReadObjectImpl(as_reference); | 524 pobj_ = ReadObjectImpl(as_reference); |
515 result->SetFieldAtOffset(offset, pobj_); | 525 result->SetFieldAtOffset(offset, pobj_); |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
768 RawTwoByteString* SnapshotReader::NewTwoByteString(intptr_t len) { | 778 RawTwoByteString* SnapshotReader::NewTwoByteString(intptr_t len) { |
769 ALLOC_NEW_OBJECT_WITH_LEN(TwoByteString, len); | 779 ALLOC_NEW_OBJECT_WITH_LEN(TwoByteString, len); |
770 } | 780 } |
771 | 781 |
772 | 782 |
773 RawTypeArguments* SnapshotReader::NewTypeArguments(intptr_t len) { | 783 RawTypeArguments* SnapshotReader::NewTypeArguments(intptr_t len) { |
774 ALLOC_NEW_OBJECT_WITH_LEN(TypeArguments, len); | 784 ALLOC_NEW_OBJECT_WITH_LEN(TypeArguments, len); |
775 } | 785 } |
776 | 786 |
777 | 787 |
| 788 RawObjectPool* SnapshotReader::NewObjectPool(intptr_t len) { |
| 789 ASSERT(kind_ == Snapshot::kFull); |
| 790 ASSERT_NO_SAFEPOINT_SCOPE(); |
| 791 RawObjectPool* obj = reinterpret_cast<RawObjectPool*>( |
| 792 AllocateUninitialized(kObjectPoolCid, ObjectPool::InstanceSize(len))); |
| 793 obj->ptr()->length_ = len; |
| 794 return obj; |
| 795 } |
| 796 |
| 797 |
| 798 RawLocalVarDescriptors* SnapshotReader::NewLocalVarDescriptors( |
| 799 intptr_t num_entries) { |
| 800 ASSERT(kind_ == Snapshot::kFull); |
| 801 ASSERT_NO_SAFEPOINT_SCOPE(); |
| 802 RawLocalVarDescriptors* obj = reinterpret_cast<RawLocalVarDescriptors*>( |
| 803 AllocateUninitialized(kLocalVarDescriptorsCid, |
| 804 LocalVarDescriptors::InstanceSize(num_entries))); |
| 805 obj->ptr()->num_entries_ = num_entries; |
| 806 return obj; |
| 807 } |
| 808 |
| 809 |
| 810 RawExceptionHandlers* SnapshotReader::NewExceptionHandlers( |
| 811 intptr_t num_entries) { |
| 812 ASSERT(kind_ == Snapshot::kFull); |
| 813 ASSERT_NO_SAFEPOINT_SCOPE(); |
| 814 RawExceptionHandlers* obj = reinterpret_cast<RawExceptionHandlers*>( |
| 815 AllocateUninitialized(kExceptionHandlersCid, |
| 816 ExceptionHandlers::InstanceSize(num_entries))); |
| 817 obj->ptr()->num_entries_ = num_entries; |
| 818 return obj; |
| 819 } |
| 820 |
| 821 |
| 822 RawPcDescriptors* SnapshotReader::NewPcDescriptors(intptr_t len) { |
| 823 ASSERT(kind_ == Snapshot::kFull); |
| 824 ASSERT_NO_SAFEPOINT_SCOPE(); |
| 825 RawPcDescriptors* obj = reinterpret_cast<RawPcDescriptors*>( |
| 826 AllocateUninitialized(kPcDescriptorsCid, |
| 827 PcDescriptors::InstanceSize(len))); |
| 828 obj->ptr()->length_ = len; |
| 829 return obj; |
| 830 } |
| 831 |
| 832 |
| 833 RawStackmap* SnapshotReader::NewStackmap(intptr_t len) { |
| 834 ASSERT(kind_ == Snapshot::kFull); |
| 835 ASSERT_NO_SAFEPOINT_SCOPE(); |
| 836 RawStackmap* obj = reinterpret_cast<RawStackmap*>( |
| 837 AllocateUninitialized(kStackmapCid, Stackmap::InstanceSize(len))); |
| 838 obj->ptr()->length_ = len; |
| 839 return obj; |
| 840 } |
| 841 |
| 842 |
| 843 RawContextScope* SnapshotReader::NewContextScope(intptr_t num_variables) { |
| 844 ASSERT(kind_ == Snapshot::kFull); |
| 845 ASSERT_NO_SAFEPOINT_SCOPE(); |
| 846 RawContextScope* obj = reinterpret_cast<RawContextScope*>( |
| 847 AllocateUninitialized(kContextScopeCid, |
| 848 ContextScope::InstanceSize(num_variables))); |
| 849 obj->ptr()->num_variables_ = num_variables; |
| 850 return obj; |
| 851 } |
| 852 |
| 853 |
| 854 RawCode* SnapshotReader::NewCode(intptr_t pointer_offsets_length) { |
| 855 ASSERT(pointer_offsets_length == 0); |
| 856 ASSERT(kind_ == Snapshot::kFull); |
| 857 ASSERT_NO_SAFEPOINT_SCOPE(); |
| 858 RawCode* obj = reinterpret_cast<RawCode*>( |
| 859 AllocateUninitialized(kCodeCid, Code::InstanceSize(0))); |
| 860 return obj; |
| 861 } |
| 862 |
| 863 |
778 RawTokenStream* SnapshotReader::NewTokenStream(intptr_t len) { | 864 RawTokenStream* SnapshotReader::NewTokenStream(intptr_t len) { |
779 ASSERT(kind_ == Snapshot::kFull); | 865 ASSERT(kind_ == Snapshot::kFull); |
780 ASSERT_NO_SAFEPOINT_SCOPE(); | 866 ASSERT_NO_SAFEPOINT_SCOPE(); |
781 stream_ = reinterpret_cast<RawTokenStream*>( | 867 stream_ = reinterpret_cast<RawTokenStream*>( |
782 AllocateUninitialized(kTokenStreamCid, TokenStream::InstanceSize())); | 868 AllocateUninitialized(kTokenStreamCid, TokenStream::InstanceSize())); |
783 uint8_t* array = const_cast<uint8_t*>(CurrentBufferAddress()); | 869 uint8_t* array = const_cast<uint8_t*>(CurrentBufferAddress()); |
784 ASSERT(array != NULL); | 870 ASSERT(array != NULL); |
785 Advance(len); | 871 Advance(len); |
786 data_ = reinterpret_cast<RawExternalTypedData*>( | 872 data_ = reinterpret_cast<RawExternalTypedData*>( |
787 AllocateUninitialized(kExternalTypedDataUint8ArrayCid, | 873 AllocateUninitialized(kExternalTypedDataUint8ArrayCid, |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
917 RawRedirectionData* SnapshotReader::NewRedirectionData() { | 1003 RawRedirectionData* SnapshotReader::NewRedirectionData() { |
918 ALLOC_NEW_OBJECT(RedirectionData); | 1004 ALLOC_NEW_OBJECT(RedirectionData); |
919 } | 1005 } |
920 | 1006 |
921 | 1007 |
922 RawFunction* SnapshotReader::NewFunction() { | 1008 RawFunction* SnapshotReader::NewFunction() { |
923 ALLOC_NEW_OBJECT(Function); | 1009 ALLOC_NEW_OBJECT(Function); |
924 } | 1010 } |
925 | 1011 |
926 | 1012 |
927 RawCode* SnapshotReader::NewCode(intptr_t pointer_offsets_length) { | |
928 ASSERT(pointer_offsets_length == 0); | |
929 ALLOC_NEW_OBJECT(Code); | |
930 } | |
931 | |
932 | |
933 RawObjectPool* SnapshotReader::NewObjectPool(intptr_t length) { | |
934 ALLOC_NEW_OBJECT(ObjectPool); | |
935 } | |
936 | |
937 | |
938 RawICData* SnapshotReader::NewICData() { | 1013 RawICData* SnapshotReader::NewICData() { |
939 ALLOC_NEW_OBJECT(ICData); | 1014 ALLOC_NEW_OBJECT(ICData); |
940 } | 1015 } |
941 | 1016 |
942 | 1017 |
| 1018 RawLinkedHashMap* SnapshotReader::NewLinkedHashMap() { |
| 1019 ALLOC_NEW_OBJECT(LinkedHashMap); |
| 1020 } |
| 1021 |
| 1022 |
943 RawMegamorphicCache* SnapshotReader::NewMegamorphicCache() { | 1023 RawMegamorphicCache* SnapshotReader::NewMegamorphicCache() { |
944 ALLOC_NEW_OBJECT(MegamorphicCache); | 1024 ALLOC_NEW_OBJECT(MegamorphicCache); |
945 } | 1025 } |
946 | 1026 |
947 | 1027 |
948 RawSubtypeTestCache* SnapshotReader::NewSubtypeTestCache() { | 1028 RawSubtypeTestCache* SnapshotReader::NewSubtypeTestCache() { |
949 ALLOC_NEW_OBJECT(SubtypeTestCache); | 1029 ALLOC_NEW_OBJECT(SubtypeTestCache); |
950 } | 1030 } |
951 | 1031 |
952 | 1032 |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1050 } | 1130 } |
1051 return Mint::NewCanonical(value); | 1131 return Mint::NewCanonical(value); |
1052 } | 1132 } |
1053 | 1133 |
1054 | 1134 |
1055 RawStacktrace* SnapshotReader::NewStacktrace() { | 1135 RawStacktrace* SnapshotReader::NewStacktrace() { |
1056 ALLOC_NEW_OBJECT(Stacktrace); | 1136 ALLOC_NEW_OBJECT(Stacktrace); |
1057 } | 1137 } |
1058 | 1138 |
1059 | 1139 |
1060 RawInstructions* SnapshotReader::GetInstructionsById(int32_t id) { | 1140 int32_t InstructionsWriter::GetOffsetFor(RawInstructions* instructions) { |
1061 // TODO(rmacnak): Read from shared library. | 1141 // Instructions are allocated with the code alignment and we don't write |
| 1142 // anything else in the text section. |
| 1143 ASSERT(Utils::IsAligned(stream_.bytes_written(), |
| 1144 OS::PreferredCodeAlignment())); |
| 1145 |
| 1146 intptr_t offset = stream_.bytes_written(); |
| 1147 stream_.WriteBytes(reinterpret_cast<uint8_t*>(instructions) - kHeapObjectTag, |
| 1148 instructions->Size()); |
| 1149 return offset; |
| 1150 } |
| 1151 |
| 1152 |
| 1153 RawInstructions* InstructionsReader::GetInstructionsAt(int32_t offset, |
| 1154 uword expected_tags) { |
| 1155 ASSERT(Utils::IsAligned(offset, OS::PreferredCodeAlignment())); |
| 1156 |
| 1157 RawInstructions* result = |
| 1158 reinterpret_cast<RawInstructions*>( |
| 1159 reinterpret_cast<uword>(buffer_) + offset + kHeapObjectTag); |
| 1160 |
| 1161 uword actual_tags = result->ptr()->tags_; |
| 1162 if (actual_tags != expected_tags) { |
| 1163 FATAL2("Instructions tag mismatch: expected %" Pd ", saw %" Pd, |
| 1164 expected_tags, |
| 1165 actual_tags); |
| 1166 } |
| 1167 |
| 1168 // TODO(rmacnak): The above contains stale pointers to a Code and an |
| 1169 // ObjectPool. Return the actual result after calling convention change. |
1062 return Instructions::null(); | 1170 return Instructions::null(); |
1063 } | 1171 } |
1064 | 1172 |
1065 | 1173 |
1066 intptr_t SnapshotReader::LookupInternalClass(intptr_t class_header) { | 1174 intptr_t SnapshotReader::LookupInternalClass(intptr_t class_header) { |
1067 // If the header is an object Id, lookup singleton VM classes or classes | 1175 // If the header is an object Id, lookup singleton VM classes or classes |
1068 // stored in the object store. | 1176 // stored in the object store. |
1069 if (IsVMIsolateObject(class_header)) { | 1177 if (IsVMIsolateObject(class_header)) { |
1070 intptr_t class_id = GetVMIsolateObjectId(class_header); | 1178 intptr_t class_id = GetVMIsolateObjectId(class_header); |
1071 ASSERT(IsSingletonClassId(class_id)); | 1179 ASSERT(IsSingletonClassId(class_id)); |
1072 return class_id; | 1180 return class_id; |
1073 } | 1181 } |
1074 ASSERT(SerializedHeaderTag::decode(class_header) == kObjectId); | 1182 ASSERT(SerializedHeaderTag::decode(class_header) == kObjectId); |
1075 intptr_t class_id = SerializedHeaderData::decode(class_header); | 1183 intptr_t class_id = SerializedHeaderData::decode(class_header); |
1076 ASSERT(IsObjectStoreClassId(class_id)); | 1184 ASSERT(IsObjectStoreClassId(class_id) || IsSingletonClassId(class_id)); |
1077 return class_id; | 1185 return class_id; |
1078 } | 1186 } |
1079 | 1187 |
1080 | 1188 |
1081 RawObject* SnapshotReader::AllocateUninitialized(intptr_t class_id, | 1189 RawObject* SnapshotReader::AllocateUninitialized(intptr_t class_id, |
1082 intptr_t size) { | 1190 intptr_t size) { |
1083 ASSERT_NO_SAFEPOINT_SCOPE(); | 1191 ASSERT_NO_SAFEPOINT_SCOPE(); |
1084 ASSERT(Utils::IsAligned(size, kObjectAlignment)); | 1192 ASSERT(Utils::IsAligned(size, kObjectAlignment)); |
1085 | 1193 |
1086 // Allocate memory where all words look like smis. This is currently | 1194 // Allocate memory where all words look like smis. This is currently |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1264 reinterpret_cast<RawObject**>(result.raw()->ptr()); | 1372 reinterpret_cast<RawObject**>(result.raw()->ptr()); |
1265 for (intptr_t i = 0; i < len; i++) { | 1373 for (intptr_t i = 0; i < len; i++) { |
1266 *PassiveObjectHandle() = ReadObjectImpl(as_reference, | 1374 *PassiveObjectHandle() = ReadObjectImpl(as_reference, |
1267 object_id, | 1375 object_id, |
1268 (i + offset)); | 1376 (i + offset)); |
1269 result.SetAt(i, *PassiveObjectHandle()); | 1377 result.SetAt(i, *PassiveObjectHandle()); |
1270 } | 1378 } |
1271 } | 1379 } |
1272 | 1380 |
1273 | 1381 |
1274 VmIsolateSnapshotReader::VmIsolateSnapshotReader(const uint8_t* buffer, | 1382 VmIsolateSnapshotReader::VmIsolateSnapshotReader( |
1275 intptr_t size, | 1383 const uint8_t* buffer, |
1276 Thread* thread) | 1384 intptr_t size, |
1277 : SnapshotReader(buffer, | 1385 const uint8_t* instructions_buffer, |
1278 size, | 1386 Thread* thread) |
1279 Snapshot::kFull, | 1387 : SnapshotReader(buffer, |
1280 new ZoneGrowableArray<BackRefNode>( | 1388 size, |
1281 kNumVmIsolateSnapshotReferences), | 1389 instructions_buffer, |
1282 thread) { | 1390 Snapshot::kFull, |
| 1391 new ZoneGrowableArray<BackRefNode>( |
| 1392 kNumVmIsolateSnapshotReferences), |
| 1393 thread) { |
1283 } | 1394 } |
1284 | 1395 |
1285 | 1396 |
1286 VmIsolateSnapshotReader::~VmIsolateSnapshotReader() { | 1397 VmIsolateSnapshotReader::~VmIsolateSnapshotReader() { |
1287 intptr_t len = GetBackwardReferenceTable()->length(); | 1398 intptr_t len = GetBackwardReferenceTable()->length(); |
1288 Object::InitVmIsolateSnapshotObjectTable(len); | 1399 Object::InitVmIsolateSnapshotObjectTable(len); |
1289 ZoneGrowableArray<BackRefNode>* backrefs = GetBackwardReferenceTable(); | 1400 ZoneGrowableArray<BackRefNode>* backrefs = GetBackwardReferenceTable(); |
1290 for (intptr_t i = 0; i < len; i++) { | 1401 for (intptr_t i = 0; i < len; i++) { |
1291 Object::vm_isolate_snapshot_object_table().SetAt( | 1402 Object::vm_isolate_snapshot_object_table().SetAt( |
1292 i, *(backrefs->At(i).reference())); | 1403 i, *(backrefs->At(i).reference())); |
1293 } | 1404 } |
1294 ResetBackwardReferenceTable(); | 1405 ResetBackwardReferenceTable(); |
| 1406 Object::set_instructions_snapshot_buffer(instructions_buffer_); |
1295 } | 1407 } |
1296 | 1408 |
1297 | 1409 |
1298 RawApiError* VmIsolateSnapshotReader::ReadVmIsolateSnapshot() { | 1410 RawApiError* VmIsolateSnapshotReader::ReadVmIsolateSnapshot() { |
1299 ASSERT(kind() == Snapshot::kFull); | 1411 ASSERT(kind() == Snapshot::kFull); |
1300 Isolate* isolate = Isolate::Current(); | 1412 Isolate* isolate = Isolate::Current(); |
1301 ASSERT(isolate != NULL); | 1413 ASSERT(isolate != NULL); |
1302 ASSERT(isolate == Dart::vm_isolate()); | 1414 ASSERT(isolate == Dart::vm_isolate()); |
1303 ObjectStore* object_store = isolate->object_store(); | 1415 ObjectStore* object_store = isolate->object_store(); |
1304 ASSERT(object_store != NULL); | 1416 ASSERT(object_store != NULL); |
(...skipping 13 matching lines...) Expand all Loading... |
1318 // Read in the symbol table. | 1430 // Read in the symbol table. |
1319 object_store->symbol_table_ = reinterpret_cast<RawArray*>(ReadObject()); | 1431 object_store->symbol_table_ = reinterpret_cast<RawArray*>(ReadObject()); |
1320 | 1432 |
1321 Symbols::InitOnceFromSnapshot(isolate); | 1433 Symbols::InitOnceFromSnapshot(isolate); |
1322 | 1434 |
1323 // Read in all the script objects and the accompanying token streams | 1435 // Read in all the script objects and the accompanying token streams |
1324 // for bootstrap libraries so that they are in the VM isolate's read | 1436 // for bootstrap libraries so that they are in the VM isolate's read |
1325 // only memory. | 1437 // only memory. |
1326 *(ArrayHandle()) ^= ReadObject(); | 1438 *(ArrayHandle()) ^= ReadObject(); |
1327 | 1439 |
| 1440 |
| 1441 if (snapshot_code()) { |
| 1442 for (intptr_t i = 0; |
| 1443 i < ArgumentsDescriptor::kCachedDescriptorCount; |
| 1444 i++) { |
| 1445 *(ArrayHandle()) ^= ReadObject(); |
| 1446 // TODO(rmacnak): |
| 1447 // ArgumentsDescriptor::InitOnceFromSnapshot(i, *(ArrayHandle())); |
| 1448 } |
| 1449 |
| 1450 ObjectPool::CheckedHandle(ReadObject()); // empty pool |
| 1451 PcDescriptors::CheckedHandle(ReadObject()); // empty pc desc |
| 1452 LocalVarDescriptors::CheckedHandle(ReadObject()); // empty var desc |
| 1453 ExceptionHandlers::CheckedHandle(ReadObject()); // empty exc handlers |
| 1454 |
| 1455 #define READ_STUB(name) \ |
| 1456 *(CodeHandle()) ^= ReadObject(); |
| 1457 // TODO(rmacnak): |
| 1458 // StubCode::name##_entry()->InitOnceFromSnapshot(CodeHandle()) |
| 1459 VM_STUB_CODE_LIST(READ_STUB); |
| 1460 #undef READ_STUB |
| 1461 } |
| 1462 |
1328 // Validate the class table. | 1463 // Validate the class table. |
1329 #if defined(DEBUG) | 1464 #if defined(DEBUG) |
1330 isolate->ValidateClassTable(); | 1465 isolate->ValidateClassTable(); |
1331 #endif | 1466 #endif |
1332 | 1467 |
1333 return ApiError::null(); | 1468 return ApiError::null(); |
1334 } | 1469 } |
1335 } | 1470 } |
1336 | 1471 |
1337 | 1472 |
1338 IsolateSnapshotReader::IsolateSnapshotReader(const uint8_t* buffer, | 1473 IsolateSnapshotReader::IsolateSnapshotReader(const uint8_t* buffer, |
1339 intptr_t size, | 1474 intptr_t size, |
| 1475 const uint8_t* instructions_buffer, |
1340 Thread* thread) | 1476 Thread* thread) |
1341 : SnapshotReader(buffer, | 1477 : SnapshotReader(buffer, |
1342 size, | 1478 size, |
| 1479 instructions_buffer, |
1343 Snapshot::kFull, | 1480 Snapshot::kFull, |
1344 new ZoneGrowableArray<BackRefNode>( | 1481 new ZoneGrowableArray<BackRefNode>( |
1345 kNumInitialReferencesInFullSnapshot), | 1482 kNumInitialReferencesInFullSnapshot), |
1346 thread) { | 1483 thread) { |
1347 } | 1484 } |
1348 | 1485 |
1349 | 1486 |
1350 IsolateSnapshotReader::~IsolateSnapshotReader() { | 1487 IsolateSnapshotReader::~IsolateSnapshotReader() { |
1351 ResetBackwardReferenceTable(); | 1488 ResetBackwardReferenceTable(); |
1352 } | 1489 } |
1353 | 1490 |
1354 | 1491 |
1355 ScriptSnapshotReader::ScriptSnapshotReader(const uint8_t* buffer, | 1492 ScriptSnapshotReader::ScriptSnapshotReader(const uint8_t* buffer, |
1356 intptr_t size, | 1493 intptr_t size, |
1357 Thread* thread) | 1494 Thread* thread) |
1358 : SnapshotReader(buffer, | 1495 : SnapshotReader(buffer, |
1359 size, | 1496 size, |
| 1497 NULL, /* instructions_buffer */ |
1360 Snapshot::kScript, | 1498 Snapshot::kScript, |
1361 new ZoneGrowableArray<BackRefNode>(kNumInitialReferences), | 1499 new ZoneGrowableArray<BackRefNode>(kNumInitialReferences), |
1362 thread) { | 1500 thread) { |
1363 } | 1501 } |
1364 | 1502 |
1365 | 1503 |
1366 ScriptSnapshotReader::~ScriptSnapshotReader() { | 1504 ScriptSnapshotReader::~ScriptSnapshotReader() { |
1367 ResetBackwardReferenceTable(); | 1505 ResetBackwardReferenceTable(); |
1368 } | 1506 } |
1369 | 1507 |
1370 | 1508 |
1371 MessageSnapshotReader::MessageSnapshotReader(const uint8_t* buffer, | 1509 MessageSnapshotReader::MessageSnapshotReader(const uint8_t* buffer, |
1372 intptr_t size, | 1510 intptr_t size, |
1373 Thread* thread) | 1511 Thread* thread) |
1374 : SnapshotReader(buffer, | 1512 : SnapshotReader(buffer, |
1375 size, | 1513 size, |
| 1514 NULL, /* instructions_buffer */ |
1376 Snapshot::kMessage, | 1515 Snapshot::kMessage, |
1377 new ZoneGrowableArray<BackRefNode>(kNumInitialReferences), | 1516 new ZoneGrowableArray<BackRefNode>(kNumInitialReferences), |
1378 thread) { | 1517 thread) { |
1379 } | 1518 } |
1380 | 1519 |
1381 | 1520 |
1382 MessageSnapshotReader::~MessageSnapshotReader() { | 1521 MessageSnapshotReader::~MessageSnapshotReader() { |
1383 ResetBackwardReferenceTable(); | 1522 ResetBackwardReferenceTable(); |
1384 } | 1523 } |
1385 | 1524 |
1386 | 1525 |
1387 SnapshotWriter::SnapshotWriter(Snapshot::Kind kind, | 1526 SnapshotWriter::SnapshotWriter(Snapshot::Kind kind, |
1388 uint8_t** buffer, | 1527 uint8_t** buffer, |
1389 ReAlloc alloc, | 1528 ReAlloc alloc, |
1390 intptr_t initial_size, | 1529 intptr_t initial_size, |
1391 ForwardList* forward_list, | 1530 ForwardList* forward_list, |
| 1531 InstructionsWriter* instructions_writer, |
1392 bool can_send_any_object, | 1532 bool can_send_any_object, |
1393 bool snapshot_code) | 1533 bool snapshot_code, |
| 1534 bool vm_isolate_is_symbolic) |
1394 : BaseWriter(buffer, alloc, initial_size), | 1535 : BaseWriter(buffer, alloc, initial_size), |
1395 kind_(kind), | 1536 kind_(kind), |
1396 thread_(Thread::Current()), | 1537 thread_(Thread::Current()), |
1397 object_store_(thread_->isolate()->object_store()), | 1538 object_store_(thread_->isolate()->object_store()), |
1398 class_table_(thread_->isolate()->class_table()), | 1539 class_table_(thread_->isolate()->class_table()), |
1399 forward_list_(forward_list), | 1540 forward_list_(forward_list), |
| 1541 instructions_writer_(instructions_writer), |
1400 exception_type_(Exceptions::kNone), | 1542 exception_type_(Exceptions::kNone), |
1401 exception_msg_(NULL), | 1543 exception_msg_(NULL), |
1402 unmarked_objects_(false), | 1544 unmarked_objects_(false), |
1403 can_send_any_object_(can_send_any_object), | 1545 can_send_any_object_(can_send_any_object), |
1404 snapshot_code_(snapshot_code) { | 1546 snapshot_code_(snapshot_code), |
| 1547 vm_isolate_is_symbolic_(vm_isolate_is_symbolic) { |
1405 ASSERT(forward_list_ != NULL); | 1548 ASSERT(forward_list_ != NULL); |
1406 } | 1549 } |
1407 | 1550 |
1408 | 1551 |
1409 void SnapshotWriter::WriteObject(RawObject* rawobj) { | 1552 void SnapshotWriter::WriteObject(RawObject* rawobj) { |
1410 WriteObjectImpl(rawobj, kAsInlinedObject); | 1553 WriteObjectImpl(rawobj, kAsInlinedObject); |
1411 WriteForwardedObjects(); | 1554 WriteForwardedObjects(); |
1412 } | 1555 } |
1413 | 1556 |
1414 #define VM_OBJECT_CLASS_LIST(V) \ | 1557 #define VM_OBJECT_CLASS_LIST(V) \ |
1415 V(OneByteString) \ | 1558 V(OneByteString) \ |
1416 V(Mint) \ | 1559 V(Mint) \ |
1417 V(Bigint) \ | 1560 V(Bigint) \ |
1418 V(Double) \ | 1561 V(Double) \ |
1419 V(ImmutableArray) \ | 1562 V(ImmutableArray) \ |
1420 | 1563 |
1421 #define VM_OBJECT_WRITE(clazz) \ | 1564 #define VM_OBJECT_WRITE(clazz) \ |
1422 case clazz::kClassId: { \ | 1565 case clazz::kClassId: { \ |
1423 object_id = forward_list_->AddObject(rawobj, kIsSerialized); \ | 1566 object_id = forward_list_->AddObject(rawobj, kIsSerialized); \ |
1424 Raw##clazz* raw_obj = reinterpret_cast<Raw##clazz*>(rawobj); \ | 1567 Raw##clazz* raw_obj = reinterpret_cast<Raw##clazz*>(rawobj); \ |
1425 raw_obj->WriteTo(this, object_id, kind()); \ | 1568 raw_obj->WriteTo(this, object_id, kind()); \ |
1426 return; \ | 1569 return true; \ |
1427 } \ | 1570 } \ |
1428 | 1571 |
1429 void SnapshotWriter::HandleVMIsolateObject(RawObject* rawobj) { | 1572 bool SnapshotWriter::HandleVMIsolateObject(RawObject* rawobj) { |
1430 // Check if it is a singleton null object. | 1573 // Check if it is a singleton null object. |
1431 if (rawobj == Object::null()) { | 1574 if (rawobj == Object::null()) { |
1432 WriteVMIsolateObject(kNullObject); | 1575 WriteVMIsolateObject(kNullObject); |
1433 return; | 1576 return true; |
1434 } | 1577 } |
1435 | 1578 |
1436 // Check if it is a singleton sentinel object. | 1579 // Check if it is a singleton sentinel object. |
1437 if (rawobj == Object::sentinel().raw()) { | 1580 if (rawobj == Object::sentinel().raw()) { |
1438 WriteVMIsolateObject(kSentinelObject); | 1581 WriteVMIsolateObject(kSentinelObject); |
1439 return; | 1582 return true; |
1440 } | 1583 } |
1441 | 1584 |
1442 // Check if it is a singleton sentinel object. | 1585 // Check if it is a singleton sentinel object. |
1443 if (rawobj == Object::transition_sentinel().raw()) { | 1586 if (rawobj == Object::transition_sentinel().raw()) { |
1444 WriteVMIsolateObject(kTransitionSentinelObject); | 1587 WriteVMIsolateObject(kTransitionSentinelObject); |
1445 return; | 1588 return true; |
1446 } | 1589 } |
1447 | 1590 |
1448 // Check if it is a singleton empty array object. | 1591 // Check if it is a singleton empty array object. |
1449 if (rawobj == Object::empty_array().raw()) { | 1592 if (rawobj == Object::empty_array().raw()) { |
1450 WriteVMIsolateObject(kEmptyArrayObject); | 1593 WriteVMIsolateObject(kEmptyArrayObject); |
1451 return; | 1594 return true; |
1452 } | 1595 } |
1453 | 1596 |
1454 // Check if it is a singleton zero array object. | 1597 // Check if it is a singleton zero array object. |
1455 if (rawobj == Object::zero_array().raw()) { | 1598 if (rawobj == Object::zero_array().raw()) { |
1456 WriteVMIsolateObject(kZeroArrayObject); | 1599 WriteVMIsolateObject(kZeroArrayObject); |
1457 return; | 1600 return true; |
1458 } | 1601 } |
1459 | 1602 |
1460 // Check if it is a singleton dyanmic Type object. | 1603 // Check if it is a singleton dyanmic Type object. |
1461 if (rawobj == Object::dynamic_type()) { | 1604 if (rawobj == Object::dynamic_type()) { |
1462 WriteVMIsolateObject(kDynamicType); | 1605 WriteVMIsolateObject(kDynamicType); |
1463 return; | 1606 return true; |
1464 } | 1607 } |
1465 | 1608 |
1466 // Check if it is a singleton void Type object. | 1609 // Check if it is a singleton void Type object. |
1467 if (rawobj == Object::void_type()) { | 1610 if (rawobj == Object::void_type()) { |
1468 WriteVMIsolateObject(kVoidType); | 1611 WriteVMIsolateObject(kVoidType); |
1469 return; | 1612 return true; |
1470 } | 1613 } |
1471 | 1614 |
1472 // Check if it is a singleton boolean true object. | 1615 // Check if it is a singleton boolean true object. |
1473 if (rawobj == Bool::True().raw()) { | 1616 if (rawobj == Bool::True().raw()) { |
1474 WriteVMIsolateObject(kTrueValue); | 1617 WriteVMIsolateObject(kTrueValue); |
1475 return; | 1618 return true; |
1476 } | 1619 } |
1477 | 1620 |
1478 // Check if it is a singleton boolean false object. | 1621 // Check if it is a singleton boolean false object. |
1479 if (rawobj == Bool::False().raw()) { | 1622 if (rawobj == Bool::False().raw()) { |
1480 WriteVMIsolateObject(kFalseValue); | 1623 WriteVMIsolateObject(kFalseValue); |
1481 return; | 1624 return true; |
1482 } | 1625 } |
1483 | 1626 |
1484 // Check if it is a singleton extractor parameter types array. | 1627 // Check if it is a singleton extractor parameter types array. |
1485 if (rawobj == Object::extractor_parameter_types().raw()) { | 1628 if (rawobj == Object::extractor_parameter_types().raw()) { |
1486 WriteVMIsolateObject(kExtractorParameterTypes); | 1629 WriteVMIsolateObject(kExtractorParameterTypes); |
1487 return; | 1630 return true; |
1488 } | 1631 } |
1489 | 1632 |
1490 // Check if it is a singleton extractor parameter names array. | 1633 // Check if it is a singleton extractor parameter names array. |
1491 if (rawobj == Object::extractor_parameter_names().raw()) { | 1634 if (rawobj == Object::extractor_parameter_names().raw()) { |
1492 WriteVMIsolateObject(kExtractorParameterNames); | 1635 WriteVMIsolateObject(kExtractorParameterNames); |
1493 return; | 1636 return true; |
1494 } | 1637 } |
1495 | 1638 |
1496 // Check if it is a singleton empty context scope object. | 1639 // Check if it is a singleton empty context scope object. |
1497 if (rawobj == Object::empty_context_scope().raw()) { | 1640 if (rawobj == Object::empty_context_scope().raw()) { |
1498 WriteVMIsolateObject(kEmptyContextScopeObject); | 1641 WriteVMIsolateObject(kEmptyContextScopeObject); |
1499 return; | 1642 return true; |
1500 } | 1643 } |
1501 | 1644 |
1502 // Check if it is a singleton class object which is shared by | 1645 // Check if it is a singleton class object which is shared by |
1503 // all isolates. | 1646 // all isolates. |
1504 intptr_t id = rawobj->GetClassId(); | 1647 intptr_t id = rawobj->GetClassId(); |
1505 if (id == kClassCid) { | 1648 if (id == kClassCid) { |
1506 RawClass* raw_class = reinterpret_cast<RawClass*>(rawobj); | 1649 RawClass* raw_class = reinterpret_cast<RawClass*>(rawobj); |
1507 intptr_t class_id = raw_class->ptr()->id_; | 1650 intptr_t class_id = raw_class->ptr()->id_; |
1508 if (IsSingletonClassId(class_id)) { | 1651 if (IsSingletonClassId(class_id)) { |
1509 intptr_t object_id = ObjectIdFromClassId(class_id); | 1652 intptr_t object_id = ObjectIdFromClassId(class_id); |
1510 WriteVMIsolateObject(object_id); | 1653 WriteVMIsolateObject(object_id); |
1511 return; | 1654 return true; |
1512 } | 1655 } |
1513 } | 1656 } |
1514 | 1657 |
1515 if (kind() == Snapshot::kFull) { | 1658 if (kind() == Snapshot::kFull) { |
1516 // Check it is a predefined symbol in the VM isolate. | 1659 // Check it is a predefined symbol in the VM isolate. |
1517 id = Symbols::LookupVMSymbol(rawobj); | 1660 id = Symbols::LookupVMSymbol(rawobj); |
1518 if (id != kInvalidIndex) { | 1661 if (id != kInvalidIndex) { |
1519 WriteVMIsolateObject(id); | 1662 WriteVMIsolateObject(id); |
1520 return; | 1663 return true; |
1521 } | 1664 } |
1522 | 1665 |
1523 // Check if it is an object from the vm isolate snapshot object table. | 1666 // Check if it is an object from the vm isolate snapshot object table. |
1524 id = FindVmSnapshotObject(rawobj); | 1667 id = FindVmSnapshotObject(rawobj); |
1525 if (id != kInvalidIndex) { | 1668 if (id != kInvalidIndex) { |
1526 WriteIndexedObject(id); | 1669 WriteIndexedObject(id); |
1527 return; | 1670 return true; |
1528 } | 1671 } |
1529 } else { | 1672 } else { |
1530 // In the case of script snapshots or for messages we do not use | 1673 // In the case of script snapshots or for messages we do not use |
1531 // the index into the vm isolate snapshot object table, instead we | 1674 // the index into the vm isolate snapshot object table, instead we |
1532 // explicitly write the object out. | 1675 // explicitly write the object out. |
1533 intptr_t object_id = forward_list_->FindObject(rawobj); | 1676 intptr_t object_id = forward_list_->FindObject(rawobj); |
1534 if (object_id != -1) { | 1677 if (object_id != -1) { |
1535 WriteIndexedObject(object_id); | 1678 WriteIndexedObject(object_id); |
1536 return; | 1679 return true; |
1537 } else { | 1680 } else { |
1538 switch (id) { | 1681 switch (id) { |
1539 VM_OBJECT_CLASS_LIST(VM_OBJECT_WRITE) | 1682 VM_OBJECT_CLASS_LIST(VM_OBJECT_WRITE) |
1540 case kTypedDataUint32ArrayCid: { | 1683 case kTypedDataUint32ArrayCid: { |
1541 object_id = forward_list_->AddObject(rawobj, kIsSerialized); | 1684 object_id = forward_list_->AddObject(rawobj, kIsSerialized); |
1542 RawTypedData* raw_obj = reinterpret_cast<RawTypedData*>(rawobj); | 1685 RawTypedData* raw_obj = reinterpret_cast<RawTypedData*>(rawobj); |
1543 raw_obj->WriteTo(this, object_id, kind()); | 1686 raw_obj->WriteTo(this, object_id, kind()); |
1544 return; | 1687 return true; |
1545 } | 1688 } |
1546 default: | 1689 default: |
1547 OS::Print("class id = %" Pd "\n", id); | 1690 OS::Print("class id = %" Pd "\n", id); |
1548 break; | 1691 break; |
1549 } | 1692 } |
1550 } | 1693 } |
1551 } | 1694 } |
1552 | 1695 |
| 1696 if (!vm_isolate_is_symbolic()) { |
| 1697 return false; |
| 1698 } |
| 1699 |
1553 const Object& obj = Object::Handle(rawobj); | 1700 const Object& obj = Object::Handle(rawobj); |
1554 FATAL1("Unexpected reference to object in VM isolate: %s\n", obj.ToCString()); | 1701 FATAL1("Unexpected reference to object in VM isolate: %s\n", obj.ToCString()); |
| 1702 return false; |
1555 } | 1703 } |
1556 | 1704 |
1557 #undef VM_OBJECT_WRITE | 1705 #undef VM_OBJECT_WRITE |
1558 | 1706 |
1559 | 1707 |
1560 // An object visitor which will iterate over all the script objects in the heap | 1708 // An object visitor which will iterate over all the script objects in the heap |
1561 // and either count them or collect them into an array. This is used during | 1709 // and either count them or collect them into an array. This is used during |
1562 // full snapshot generation of the VM isolate to write out all script | 1710 // full snapshot generation of the VM isolate to write out all script |
1563 // objects and their accompanying token streams. | 1711 // objects and their accompanying token streams. |
1564 class ScriptVisitor : public ObjectVisitor { | 1712 class ScriptVisitor : public ObjectVisitor { |
(...skipping 24 matching lines...) Expand all Loading... |
1589 | 1737 |
1590 private: | 1738 private: |
1591 Object& objHandle_; | 1739 Object& objHandle_; |
1592 intptr_t count_; | 1740 intptr_t count_; |
1593 const Array* scripts_; | 1741 const Array* scripts_; |
1594 }; | 1742 }; |
1595 | 1743 |
1596 | 1744 |
1597 FullSnapshotWriter::FullSnapshotWriter(uint8_t** vm_isolate_snapshot_buffer, | 1745 FullSnapshotWriter::FullSnapshotWriter(uint8_t** vm_isolate_snapshot_buffer, |
1598 uint8_t** isolate_snapshot_buffer, | 1746 uint8_t** isolate_snapshot_buffer, |
| 1747 uint8_t** instructions_snapshot_buffer, |
1599 ReAlloc alloc, | 1748 ReAlloc alloc, |
1600 bool snapshot_code) | 1749 bool snapshot_code, |
| 1750 bool vm_isolate_is_symbolic) |
1601 : isolate_(Isolate::Current()), | 1751 : isolate_(Isolate::Current()), |
1602 vm_isolate_snapshot_buffer_(vm_isolate_snapshot_buffer), | 1752 vm_isolate_snapshot_buffer_(vm_isolate_snapshot_buffer), |
1603 isolate_snapshot_buffer_(isolate_snapshot_buffer), | 1753 isolate_snapshot_buffer_(isolate_snapshot_buffer), |
| 1754 instructions_snapshot_buffer_(instructions_snapshot_buffer), |
1604 alloc_(alloc), | 1755 alloc_(alloc), |
1605 vm_isolate_snapshot_size_(0), | 1756 vm_isolate_snapshot_size_(0), |
1606 isolate_snapshot_size_(0), | 1757 isolate_snapshot_size_(0), |
| 1758 instructions_snapshot_size_(0), |
1607 forward_list_(NULL), | 1759 forward_list_(NULL), |
| 1760 instructions_writer_(NULL), |
1608 scripts_(Array::Handle(isolate_)), | 1761 scripts_(Array::Handle(isolate_)), |
1609 symbol_table_(Array::Handle(isolate_)), | 1762 symbol_table_(Array::Handle(isolate_)), |
1610 snapshot_code_(snapshot_code) { | 1763 snapshot_code_(snapshot_code), |
| 1764 vm_isolate_is_symbolic_(vm_isolate_is_symbolic) { |
1611 ASSERT(isolate_snapshot_buffer_ != NULL); | 1765 ASSERT(isolate_snapshot_buffer_ != NULL); |
1612 ASSERT(alloc_ != NULL); | 1766 ASSERT(alloc_ != NULL); |
1613 ASSERT(isolate_ != NULL); | 1767 ASSERT(isolate_ != NULL); |
1614 ASSERT(ClassFinalizer::AllClassesFinalized()); | 1768 ASSERT(ClassFinalizer::AllClassesFinalized()); |
1615 ObjectStore* object_store = isolate_->object_store(); | 1769 ObjectStore* object_store = isolate_->object_store(); |
1616 ASSERT(object_store != NULL); | 1770 ASSERT(object_store != NULL); |
1617 Heap* heap = isolate_->heap(); | 1771 Heap* heap = isolate_->heap(); |
1618 ASSERT(heap != NULL); | 1772 ASSERT(heap != NULL); |
1619 // Ensure the class table is valid. | 1773 // Ensure the class table is valid. |
1620 #if defined(DEBUG) | 1774 #if defined(DEBUG) |
(...skipping 13 matching lines...) Expand all Loading... |
1634 heap->IterateOldObjects(&script_visitor); | 1788 heap->IterateOldObjects(&script_visitor); |
1635 | 1789 |
1636 // Stash the symbol table away for writing and reading into the vm isolate, | 1790 // Stash the symbol table away for writing and reading into the vm isolate, |
1637 // and reset the symbol table for the regular isolate so that we do not | 1791 // and reset the symbol table for the regular isolate so that we do not |
1638 // write these symbols into the snapshot of a regular dart isolate. | 1792 // write these symbols into the snapshot of a regular dart isolate. |
1639 symbol_table_ = object_store->symbol_table(); | 1793 symbol_table_ = object_store->symbol_table(); |
1640 Symbols::SetupSymbolTable(isolate_); | 1794 Symbols::SetupSymbolTable(isolate_); |
1641 | 1795 |
1642 forward_list_ = new ForwardList(SnapshotWriter::FirstObjectId()); | 1796 forward_list_ = new ForwardList(SnapshotWriter::FirstObjectId()); |
1643 ASSERT(forward_list_ != NULL); | 1797 ASSERT(forward_list_ != NULL); |
| 1798 |
| 1799 if (instructions_snapshot_buffer != NULL) { |
| 1800 instructions_writer_ = new InstructionsWriter(instructions_snapshot_buffer, |
| 1801 alloc, |
| 1802 kInitialSize); |
| 1803 } |
1644 } | 1804 } |
1645 | 1805 |
1646 | 1806 |
1647 FullSnapshotWriter::~FullSnapshotWriter() { | 1807 FullSnapshotWriter::~FullSnapshotWriter() { |
1648 delete forward_list_; | 1808 delete forward_list_; |
1649 symbol_table_ = Array::null(); | 1809 symbol_table_ = Array::null(); |
1650 scripts_ = Array::null(); | 1810 scripts_ = Array::null(); |
1651 } | 1811 } |
1652 | 1812 |
1653 | 1813 |
1654 void FullSnapshotWriter::WriteVmIsolateSnapshot() { | 1814 void FullSnapshotWriter::WriteVmIsolateSnapshot() { |
1655 ASSERT(vm_isolate_snapshot_buffer_ != NULL); | 1815 ASSERT(vm_isolate_snapshot_buffer_ != NULL); |
1656 SnapshotWriter writer(Snapshot::kFull, | 1816 SnapshotWriter writer(Snapshot::kFull, |
1657 vm_isolate_snapshot_buffer_, | 1817 vm_isolate_snapshot_buffer_, |
1658 alloc_, | 1818 alloc_, |
1659 kInitialSize, | 1819 kInitialSize, |
1660 forward_list_, | 1820 forward_list_, |
| 1821 instructions_writer_, |
1661 true, /* can_send_any_object */ | 1822 true, /* can_send_any_object */ |
1662 snapshot_code_); | 1823 snapshot_code_, |
| 1824 vm_isolate_is_symbolic_); |
1663 // Write full snapshot for the VM isolate. | 1825 // Write full snapshot for the VM isolate. |
1664 // Setup for long jump in case there is an exception while writing | 1826 // Setup for long jump in case there is an exception while writing |
1665 // the snapshot. | 1827 // the snapshot. |
1666 LongJumpScope jump; | 1828 LongJumpScope jump; |
1667 if (setjmp(*jump.Set()) == 0) { | 1829 if (setjmp(*jump.Set()) == 0) { |
1668 // Reserve space in the output buffer for a snapshot header. | 1830 // Reserve space in the output buffer for a snapshot header. |
1669 writer.ReserveHeader(); | 1831 writer.ReserveHeader(); |
1670 | 1832 |
1671 // Write out the version string. | 1833 // Write out the version string. |
1672 writer.WriteVersion(); | 1834 writer.WriteVersion(); |
1673 | 1835 |
1674 /* | 1836 /* |
1675 * Now Write out the following | 1837 * Now Write out the following |
1676 * - the symbol table | 1838 * - the symbol table |
1677 * - all the scripts and token streams for these scripts | 1839 * - all the scripts and token streams for these scripts |
1678 * | 1840 * |
1679 **/ | 1841 **/ |
1680 // Write out the symbol table. | 1842 // Write out the symbol table. |
1681 writer.WriteObject(symbol_table_.raw()); | 1843 writer.WriteObject(symbol_table_.raw()); |
1682 | 1844 |
1683 // Write out all the script objects and the accompanying token streams | 1845 // Write out all the script objects and the accompanying token streams |
1684 // for the bootstrap libraries so that they are in the VM isolate | 1846 // for the bootstrap libraries so that they are in the VM isolate |
1685 // read only memory. | 1847 // read only memory. |
1686 writer.WriteObject(scripts_.raw()); | 1848 writer.WriteObject(scripts_.raw()); |
1687 | 1849 |
1688 // Write out all forwarded objects. | 1850 if (snapshot_code_) { |
1689 writer.WriteForwardedObjects(); | 1851 ASSERT(!vm_isolate_is_symbolic_); |
| 1852 |
| 1853 for (intptr_t i = 0; |
| 1854 i < ArgumentsDescriptor::kCachedDescriptorCount; |
| 1855 i++) { |
| 1856 writer.WriteObject(ArgumentsDescriptor::cached_args_descriptors_[i]); |
| 1857 } |
| 1858 |
| 1859 writer.WriteObject(Object::empty_object_pool().raw()); |
| 1860 writer.WriteObject(Object::empty_descriptors().raw()); |
| 1861 writer.WriteObject(Object::empty_var_descriptors().raw()); |
| 1862 writer.WriteObject(Object::empty_exception_handlers().raw()); |
| 1863 |
| 1864 #define WRITE_STUB(name) \ |
| 1865 writer.WriteObject(StubCode::name##_entry()->code()); |
| 1866 VM_STUB_CODE_LIST(WRITE_STUB); |
| 1867 #undef WRITE_STUB |
| 1868 } |
| 1869 |
1690 | 1870 |
1691 writer.FillHeader(writer.kind()); | 1871 writer.FillHeader(writer.kind()); |
1692 | 1872 |
1693 vm_isolate_snapshot_size_ = writer.BytesWritten(); | 1873 vm_isolate_snapshot_size_ = writer.BytesWritten(); |
1694 } else { | 1874 } else { |
1695 writer.ThrowException(writer.exception_type(), writer.exception_msg()); | 1875 writer.ThrowException(writer.exception_type(), writer.exception_msg()); |
1696 } | 1876 } |
1697 } | 1877 } |
1698 | 1878 |
1699 | 1879 |
1700 void FullSnapshotWriter::WriteIsolateFullSnapshot() { | 1880 void FullSnapshotWriter::WriteIsolateFullSnapshot() { |
1701 SnapshotWriter writer(Snapshot::kFull, | 1881 SnapshotWriter writer(Snapshot::kFull, |
1702 isolate_snapshot_buffer_, | 1882 isolate_snapshot_buffer_, |
1703 alloc_, | 1883 alloc_, |
1704 kInitialSize, | 1884 kInitialSize, |
1705 forward_list_, | 1885 forward_list_, |
| 1886 instructions_writer_, |
1706 true, /* can_send_any_object */ | 1887 true, /* can_send_any_object */ |
1707 snapshot_code_); | 1888 snapshot_code_, |
| 1889 true /* vm_isolate_is_symbolic */); |
1708 ObjectStore* object_store = isolate_->object_store(); | 1890 ObjectStore* object_store = isolate_->object_store(); |
1709 ASSERT(object_store != NULL); | 1891 ASSERT(object_store != NULL); |
1710 | 1892 |
1711 // Write full snapshot for a regular isolate. | 1893 // Write full snapshot for a regular isolate. |
1712 // Setup for long jump in case there is an exception while writing | 1894 // Setup for long jump in case there is an exception while writing |
1713 // the snapshot. | 1895 // the snapshot. |
1714 LongJumpScope jump; | 1896 LongJumpScope jump; |
1715 if (setjmp(*jump.Set()) == 0) { | 1897 if (setjmp(*jump.Set()) == 0) { |
1716 // Reserve space in the output buffer for a snapshot header. | 1898 // Reserve space in the output buffer for a snapshot header. |
1717 writer.ReserveHeader(); | 1899 writer.ReserveHeader(); |
(...skipping 14 matching lines...) Expand all Loading... |
1732 writer.FillHeader(writer.kind()); | 1914 writer.FillHeader(writer.kind()); |
1733 writer.UnmarkAll(); | 1915 writer.UnmarkAll(); |
1734 | 1916 |
1735 isolate_snapshot_size_ = writer.BytesWritten(); | 1917 isolate_snapshot_size_ = writer.BytesWritten(); |
1736 } else { | 1918 } else { |
1737 writer.ThrowException(writer.exception_type(), writer.exception_msg()); | 1919 writer.ThrowException(writer.exception_type(), writer.exception_msg()); |
1738 } | 1920 } |
1739 } | 1921 } |
1740 | 1922 |
1741 | 1923 |
| 1924 class WritableVMIsolateScope : StackResource { |
| 1925 public: |
| 1926 explicit WritableVMIsolateScope(Thread* thread) : StackResource(thread) { |
| 1927 Dart::vm_isolate()->heap()->WriteProtect(false); |
| 1928 } |
| 1929 |
| 1930 ~WritableVMIsolateScope() { |
| 1931 ASSERT(Dart::vm_isolate()->heap()->UsedInWords(Heap::kNew) == 0); |
| 1932 Dart::vm_isolate()->heap()->WriteProtect(true); |
| 1933 } |
| 1934 }; |
| 1935 |
| 1936 |
1742 void FullSnapshotWriter::WriteFullSnapshot() { | 1937 void FullSnapshotWriter::WriteFullSnapshot() { |
1743 if (vm_isolate_snapshot_buffer() != NULL) { | 1938 if (!vm_isolate_is_symbolic_) { |
1744 WriteVmIsolateSnapshot(); | 1939 // TODO(asiva): Don't mutate object headers during serialization. |
| 1940 WritableVMIsolateScope scope(Thread::Current()); |
| 1941 |
| 1942 if (vm_isolate_snapshot_buffer() != NULL) { |
| 1943 WriteVmIsolateSnapshot(); |
| 1944 } |
| 1945 WriteIsolateFullSnapshot(); |
| 1946 |
| 1947 instructions_snapshot_size_ = instructions_writer_->BytesWritten(); |
| 1948 } else { |
| 1949 if (vm_isolate_snapshot_buffer() != NULL) { |
| 1950 WriteVmIsolateSnapshot(); |
| 1951 } |
| 1952 WriteIsolateFullSnapshot(); |
1745 } | 1953 } |
1746 WriteIsolateFullSnapshot(); | |
1747 } | 1954 } |
1748 | 1955 |
1749 | 1956 |
1750 PrecompiledSnapshotWriter::PrecompiledSnapshotWriter( | 1957 PrecompiledSnapshotWriter::PrecompiledSnapshotWriter( |
1751 uint8_t** vm_isolate_snapshot_buffer, | 1958 uint8_t** vm_isolate_snapshot_buffer, |
1752 uint8_t** isolate_snapshot_buffer, | 1959 uint8_t** isolate_snapshot_buffer, |
| 1960 uint8_t** instructions_snapshot_buffer, |
1753 ReAlloc alloc) | 1961 ReAlloc alloc) |
1754 : FullSnapshotWriter(vm_isolate_snapshot_buffer, | 1962 : FullSnapshotWriter(vm_isolate_snapshot_buffer, |
1755 isolate_snapshot_buffer, | 1963 isolate_snapshot_buffer, |
| 1964 instructions_snapshot_buffer, |
1756 alloc, | 1965 alloc, |
1757 true /* snapshot_code */) { | 1966 true, /* snapshot_code */ |
| 1967 false /* vm_isolate_is_symbolic */) { |
1758 } | 1968 } |
1759 | 1969 |
1760 | 1970 |
1761 PrecompiledSnapshotWriter::~PrecompiledSnapshotWriter() {} | 1971 PrecompiledSnapshotWriter::~PrecompiledSnapshotWriter() {} |
1762 | 1972 |
1763 | 1973 |
1764 uword SnapshotWriter::GetObjectTags(RawObject* raw) { | 1974 uword SnapshotWriter::GetObjectTags(RawObject* raw) { |
1765 uword tags = raw->ptr()->tags_; | 1975 uword tags = raw->ptr()->tags_; |
1766 if (SerializedHeaderTag::decode(tags) == kObjectId) { | 1976 if (SerializedHeaderTag::decode(tags) == kObjectId) { |
1767 intptr_t id = SerializedHeaderData::decode(tags); | 1977 intptr_t id = SerializedHeaderData::decode(tags); |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1877 uword tags = rawobj->ptr()->tags_; | 2087 uword tags = rawobj->ptr()->tags_; |
1878 if (SerializedHeaderTag::decode(tags) == kObjectId) { | 2088 if (SerializedHeaderTag::decode(tags) == kObjectId) { |
1879 intptr_t id = SerializedHeaderData::decode(tags); | 2089 intptr_t id = SerializedHeaderData::decode(tags); |
1880 WriteIndexedObject(id); | 2090 WriteIndexedObject(id); |
1881 return true; | 2091 return true; |
1882 } | 2092 } |
1883 | 2093 |
1884 // Now check if it is an object from the VM isolate (NOTE: premarked objects | 2094 // Now check if it is an object from the VM isolate (NOTE: premarked objects |
1885 // are considered to be objects in the VM isolate). These objects are shared | 2095 // are considered to be objects in the VM isolate). These objects are shared |
1886 // by all isolates. | 2096 // by all isolates. |
1887 if (rawobj->IsVMHeapObject()) { | 2097 if (rawobj->IsVMHeapObject() && HandleVMIsolateObject(rawobj)) { |
1888 HandleVMIsolateObject(rawobj); | |
1889 return true; | 2098 return true; |
1890 } | 2099 } |
1891 | 2100 |
1892 // Check if it is a code object in that case just write a Null object | 2101 // Check if it is a code object in that case just write a Null object |
1893 // as we do not want code objects in the snapshot. | 2102 // as we do not want code objects in the snapshot. |
1894 if (cid == kCodeCid && !snapshot_code()) { | 2103 if (cid == kCodeCid && !snapshot_code()) { |
1895 WriteVMIsolateObject(kNullObject); | 2104 WriteVMIsolateObject(kNullObject); |
1896 return true; | 2105 return true; |
1897 } | 2106 } |
1898 | 2107 |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2070 case kTypedData##clazz##ViewCid: \ | 2279 case kTypedData##clazz##ViewCid: \ |
2071 | 2280 |
2072 CLASS_LIST_TYPED_DATA(SNAPSHOT_WRITE) | 2281 CLASS_LIST_TYPED_DATA(SNAPSHOT_WRITE) |
2073 case kByteDataViewCid: { | 2282 case kByteDataViewCid: { |
2074 WriteInstance(object_id, raw, cls, tags); | 2283 WriteInstance(object_id, raw, cls, tags); |
2075 return; | 2284 return; |
2076 } | 2285 } |
2077 #undef SNAPSHOT_WRITE | 2286 #undef SNAPSHOT_WRITE |
2078 default: break; | 2287 default: break; |
2079 } | 2288 } |
2080 UNREACHABLE(); | 2289 |
| 2290 const Object& obj = Object::Handle(raw); |
| 2291 FATAL1("Unexpected inlined object: %s\n", obj.ToCString()); |
2081 } | 2292 } |
2082 | 2293 |
2083 | 2294 |
2084 class WriteInlinedObjectVisitor : public ObjectVisitor { | 2295 class WriteInlinedObjectVisitor : public ObjectVisitor { |
2085 public: | 2296 public: |
2086 explicit WriteInlinedObjectVisitor(SnapshotWriter* writer) | 2297 explicit WriteInlinedObjectVisitor(SnapshotWriter* writer) |
2087 : ObjectVisitor(Isolate::Current()), writer_(writer) {} | 2298 : ObjectVisitor(Isolate::Current()), writer_(writer) {} |
2088 | 2299 |
2089 virtual void VisitObject(RawObject* obj) { | 2300 virtual void VisitObject(RawObject* obj) { |
2090 writer_->WriteInlinedObject(obj); | 2301 writer_->WriteInlinedObject(obj); |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2266 } | 2477 } |
2267 | 2478 |
2268 | 2479 |
2269 void SnapshotWriter::WriteInstance(intptr_t object_id, | 2480 void SnapshotWriter::WriteInstance(intptr_t object_id, |
2270 RawObject* raw, | 2481 RawObject* raw, |
2271 RawClass* cls, | 2482 RawClass* cls, |
2272 intptr_t tags) { | 2483 intptr_t tags) { |
2273 // Check if the instance has native fields and throw an exception if it does. | 2484 // Check if the instance has native fields and throw an exception if it does. |
2274 CheckForNativeFields(cls); | 2485 CheckForNativeFields(cls); |
2275 | 2486 |
2276 // Check if object is a closure that is serializable, if the object is a | 2487 if ((kind() == Snapshot::kMessage) || (kind() == Snapshot::kScript)) { |
2277 // closure that is not serializable this will throw an exception. | 2488 // Check if object is a closure that is serializable, if the object is a |
2278 RawFunction* func = IsSerializableClosure(cls, raw); | 2489 // closure that is not serializable this will throw an exception. |
2279 if (func != Function::null()) { | 2490 RawFunction* func = IsSerializableClosure(cls, raw); |
2280 WriteStaticImplicitClosure(object_id, func, tags); | 2491 if (func != Function::null()) { |
2281 return; | 2492 WriteStaticImplicitClosure(object_id, func, tags); |
| 2493 return; |
| 2494 } |
2282 } | 2495 } |
2283 | 2496 |
2284 // Object is regular dart instance. | 2497 // Object is regular dart instance. |
2285 intptr_t next_field_offset = Class::IsSignatureClass(cls) ? | 2498 intptr_t next_field_offset = Class::IsSignatureClass(cls) ? |
2286 Closure::InstanceSize() : | 2499 Closure::InstanceSize() : |
2287 cls->ptr()->next_field_offset_in_words_ << kWordSizeLog2; | 2500 cls->ptr()->next_field_offset_in_words_ << kWordSizeLog2; |
2288 ASSERT(next_field_offset > 0); | 2501 ASSERT(next_field_offset > 0); |
2289 | 2502 |
2290 // Write out the serialization header value for this object. | 2503 // Write out the serialization header value for this object. |
2291 WriteInlinedObjectHeader(object_id); | 2504 WriteInlinedObjectHeader(object_id); |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2401 } | 2614 } |
2402 | 2615 |
2403 | 2616 |
2404 ScriptSnapshotWriter::ScriptSnapshotWriter(uint8_t** buffer, | 2617 ScriptSnapshotWriter::ScriptSnapshotWriter(uint8_t** buffer, |
2405 ReAlloc alloc) | 2618 ReAlloc alloc) |
2406 : SnapshotWriter(Snapshot::kScript, | 2619 : SnapshotWriter(Snapshot::kScript, |
2407 buffer, | 2620 buffer, |
2408 alloc, | 2621 alloc, |
2409 kInitialSize, | 2622 kInitialSize, |
2410 &forward_list_, | 2623 &forward_list_, |
| 2624 NULL, /* instructions_writer */ |
2411 true, /* can_send_any_object */ | 2625 true, /* can_send_any_object */ |
2412 false /* snapshot_code */), | 2626 false, /* snapshot_code */ |
| 2627 true /* vm_isolate_is_symbolic */), |
2413 forward_list_(kMaxPredefinedObjectIds) { | 2628 forward_list_(kMaxPredefinedObjectIds) { |
2414 ASSERT(buffer != NULL); | 2629 ASSERT(buffer != NULL); |
2415 ASSERT(alloc != NULL); | 2630 ASSERT(alloc != NULL); |
2416 } | 2631 } |
2417 | 2632 |
2418 | 2633 |
2419 void ScriptSnapshotWriter::WriteScriptSnapshot(const Library& lib) { | 2634 void ScriptSnapshotWriter::WriteScriptSnapshot(const Library& lib) { |
2420 ASSERT(kind() == Snapshot::kScript); | 2635 ASSERT(kind() == Snapshot::kScript); |
2421 ASSERT(isolate() != NULL); | 2636 ASSERT(isolate() != NULL); |
2422 ASSERT(ClassFinalizer::AllClassesFinalized()); | 2637 ASSERT(ClassFinalizer::AllClassesFinalized()); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2456 | 2671 |
2457 | 2672 |
2458 MessageWriter::MessageWriter(uint8_t** buffer, | 2673 MessageWriter::MessageWriter(uint8_t** buffer, |
2459 ReAlloc alloc, | 2674 ReAlloc alloc, |
2460 bool can_send_any_object) | 2675 bool can_send_any_object) |
2461 : SnapshotWriter(Snapshot::kMessage, | 2676 : SnapshotWriter(Snapshot::kMessage, |
2462 buffer, | 2677 buffer, |
2463 alloc, | 2678 alloc, |
2464 kInitialSize, | 2679 kInitialSize, |
2465 &forward_list_, | 2680 &forward_list_, |
| 2681 NULL, /* instructions_writer */ |
2466 can_send_any_object, | 2682 can_send_any_object, |
2467 false /* snapshot_code */), | 2683 false, /* snapshot_code */ |
| 2684 true /* vm_isolate_is_symbolic */), |
2468 forward_list_(kMaxPredefinedObjectIds) { | 2685 forward_list_(kMaxPredefinedObjectIds) { |
2469 ASSERT(buffer != NULL); | 2686 ASSERT(buffer != NULL); |
2470 ASSERT(alloc != NULL); | 2687 ASSERT(alloc != NULL); |
2471 } | 2688 } |
2472 | 2689 |
2473 | 2690 |
2474 void MessageWriter::WriteMessage(const Object& obj) { | 2691 void MessageWriter::WriteMessage(const Object& obj) { |
2475 ASSERT(kind() == Snapshot::kMessage); | 2692 ASSERT(kind() == Snapshot::kMessage); |
2476 ASSERT(isolate() != NULL); | 2693 ASSERT(isolate() != NULL); |
2477 | 2694 |
2478 // Setup for long jump in case there is an exception while writing | 2695 // Setup for long jump in case there is an exception while writing |
2479 // the message. | 2696 // the message. |
2480 LongJumpScope jump; | 2697 LongJumpScope jump; |
2481 if (setjmp(*jump.Set()) == 0) { | 2698 if (setjmp(*jump.Set()) == 0) { |
2482 NoSafepointScope no_safepoint; | 2699 NoSafepointScope no_safepoint; |
2483 WriteObject(obj.raw()); | 2700 WriteObject(obj.raw()); |
2484 UnmarkAll(); | 2701 UnmarkAll(); |
2485 } else { | 2702 } else { |
2486 ThrowException(exception_type(), exception_msg()); | 2703 ThrowException(exception_type(), exception_msg()); |
2487 } | 2704 } |
2488 } | 2705 } |
2489 | 2706 |
2490 | 2707 |
2491 } // namespace dart | 2708 } // namespace dart |
OLD | NEW |