OLD | NEW |
---|---|
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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/isolate_reload.h" | 5 #include "vm/isolate_reload.h" |
6 | 6 |
7 #include "vm/become.h" | 7 #include "vm/become.h" |
8 #include "vm/code_generator.h" | 8 #include "vm/code_generator.h" |
9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
10 #include "vm/dart_api_impl.h" | 10 #include "vm/dart_api_impl.h" |
(...skipping 26 matching lines...) Expand all Loading... | |
37 | 37 |
38 #define I (isolate()) | 38 #define I (isolate()) |
39 #define Z (thread->zone()) | 39 #define Z (thread->zone()) |
40 | 40 |
41 #define TIMELINE_SCOPE(name) \ | 41 #define TIMELINE_SCOPE(name) \ |
42 TimelineDurationScope tds##name(Thread::Current(), \ | 42 TimelineDurationScope tds##name(Thread::Current(), \ |
43 Timeline::GetIsolateStream(), \ | 43 Timeline::GetIsolateStream(), \ |
44 #name) | 44 #name) |
45 | 45 |
46 | 46 |
47 InstanceMorpher::InstanceMorpher(const Class& from, const Class& to) | |
48 : from_(from), to_(to), mapping_() { | |
49 ComputeMapping(); | |
50 before_ = new ZoneGrowableArray<const Instance*>(); | |
51 after_ = new ZoneGrowableArray<const Instance*>(); | |
52 ASSERT(from_.id() == to_.id()); | |
53 cid_ = from_.id(); | |
54 } | |
55 | |
56 | |
57 void InstanceMorpher::AddObject(RawObject* object) const { | |
58 ASSERT(object->GetClassId() == cid()); | |
59 const Instance& instance = Instance::Cast(Object::Handle(object)); | |
60 before_->Add(&instance); | |
61 } | |
62 | |
63 | |
64 void InstanceMorpher::ComputeMapping() { | |
65 if (from_.NumTypeArguments()) { | |
66 // Add copying of the optional type argument field. | |
67 intptr_t from_offset = from_.type_arguments_field_offset(); | |
68 ASSERT(from_offset != Class::kNoTypeArguments); | |
69 intptr_t to_offset = to_.type_arguments_field_offset(); | |
70 ASSERT(to_offset != Class::kNoTypeArguments); | |
71 mapping_.Add(from_offset); | |
72 mapping_.Add(to_offset); | |
73 } | |
74 | |
75 // Add copying of the instance fields if matching by name. | |
76 // Note: currently the type of the fields are ignored. | |
77 const Array& from_fields = Array::Handle(from_.OffsetToFieldMap()); | |
78 const Array& to_fields = Array::Handle(to_.OffsetToFieldMap()); | |
79 Field& from_field = Field::Handle(); | |
80 Field& to_field = Field::Handle(); | |
81 String& from_name = String::Handle(); | |
82 String& to_name = String::Handle(); | |
83 for (intptr_t i = 0; i < from_fields.Length(); i++) { | |
84 if (from_fields.At(i) == Field::null()) continue; // Ignore non-fields. | |
85 from_field = Field::RawCast(from_fields.At(i)); | |
86 ASSERT(from_field.is_instance()); | |
87 from_name = from_field.name(); | |
88 // We now have to find where this field is in the to class. | |
89 for (intptr_t j = 0; j < to_fields.Length(); j++) { | |
90 if (to_fields.At(j) == Field::null()) continue; // Ignore non-fields. | |
91 to_field = Field::RawCast(to_fields.At(j)); | |
92 ASSERT(to_field.is_instance()); | |
93 to_name = to_field.name(); | |
94 if (from_name.Equals(to_name)) { | |
95 // Success | |
96 mapping_.Add(from_field.Offset()); | |
97 mapping_.Add(to_field.Offset()); | |
98 } | |
99 } | |
100 } | |
101 } | |
102 | |
103 | |
104 RawInstance* InstanceMorpher::Morph(const Instance& instance) const { | |
105 const Instance& result = Instance::Handle(Instance::New(to_)); | |
106 // Morph the context from instance to result using mapping_. | |
107 for (intptr_t i = 0; i < mapping_.length(); i +=2) { | |
108 intptr_t from_offset = mapping_.At(i); | |
109 intptr_t to_offset = mapping_.At(i+1); | |
110 const Object& value = | |
111 Object::Handle(instance.RawGetFieldAtOffset(from_offset)); | |
112 result.RawSetFieldAtOffset(to_offset, value); | |
113 } | |
114 // Convert the instance into a filler object. | |
115 Become::MakeDummyObject(instance); | |
116 return result.raw(); | |
117 } | |
118 | |
119 | |
120 void InstanceMorpher::CreateMorphedCopies() const { | |
121 for (intptr_t i = 0; i < before()->length(); i++) { | |
122 const Instance& copy = Instance::Handle(Morph(*before()->At(i))); | |
123 after()->Add(©); | |
124 } | |
125 } | |
126 | |
127 | |
128 void InstanceMorpher::DumpFormatFor(const Class& cls) const { | |
129 OS::Print("%s\n", cls.ToCString()); | |
Cutch
2016/07/26 14:42:45
Use a LogBlock scope object and THR_Print so multi
bakster
2016/07/26 16:54:51
Done.
| |
130 if (cls.NumTypeArguments()) { | |
131 intptr_t field_offset = cls.type_arguments_field_offset(); | |
132 ASSERT(field_offset != Class::kNoTypeArguments); | |
133 OS::Print(" - @%" Pd " <type arguments>\n", field_offset); | |
134 } | |
135 const Array& fields = Array::Handle(cls.OffsetToFieldMap()); | |
136 Field& field = Field::Handle(); | |
137 String& name = String::Handle(); | |
138 for (intptr_t i = 0; i < fields.Length(); i++) { | |
139 if (fields.At(i) != Field::null()) { | |
140 field = Field::RawCast(fields.At(i)); | |
141 ASSERT(field.is_instance()); | |
142 name = field.name(); | |
143 OS::Print(" - @%" Pd " %s\n", field.Offset(), name.ToCString()); | |
144 } | |
145 } | |
146 | |
147 OS::Print("Mapping: "); | |
148 for (int i = 0; i < mapping_.length(); i +=2) { | |
149 OS::Print(" %" Pd "->%" Pd, mapping_.At(i), mapping_.At(i+1)); | |
150 } | |
151 OS::Print("\n"); | |
152 } | |
153 | |
154 | |
155 void InstanceMorpher::Dump() const { | |
156 OS::Print("Morphing from "); | |
Cutch
2016/07/26 14:42:45
here too
bakster
2016/07/26 16:54:51
Done.
| |
157 DumpFormatFor(from_); | |
158 OS::Print("To "); | |
159 DumpFormatFor(to_); | |
160 OS::Print("\n"); | |
161 } | |
162 | |
163 | |
164 void ReasonForCancelling::Report(IsolateReloadContext* context) { | |
165 const Error& error = Error::Handle(ToError()); | |
166 context->ReportError(error); | |
167 } | |
168 | |
169 | |
170 RawError* ReasonForCancelling::ToError() { | |
171 // By default create the error returned from ToString. | |
172 const String& message = String::Handle(ToString()); | |
173 OS::Print("[[%s]]\n", message.ToCString()); | |
Cutch
2016/07/26 14:42:46
We should print these to a JSONStream object inste
| |
174 return LanguageError::New(message); | |
175 } | |
176 | |
177 | |
178 RawString* ReasonForCancelling::ToString() { | |
179 UNREACHABLE(); | |
180 return NULL; | |
181 } | |
182 | |
183 | |
184 RawError* IsolateReloadContext::error() const { | |
185 ASSERT(has_error()); | |
186 // Report the first error to the surroundings. | |
187 const Error& error = | |
188 Error::Handle(reasons_to_cancel_reload_.At(0)->ToError()); | |
189 OS::Print("[[%s]]\n", error.ToCString()); | |
Cutch
2016/07/26 14:42:45
We should print these to a JSONStream object inste
bakster
2016/07/26 16:54:51
For now, I removed the print statement since it is
| |
190 return error.raw(); | |
191 } | |
192 | |
47 class ScriptUrlSetTraits { | 193 class ScriptUrlSetTraits { |
48 public: | 194 public: |
49 static bool ReportStats() { return false; } | 195 static bool ReportStats() { return false; } |
50 static const char* Name() { return "ScriptUrlSetTraits"; } | 196 static const char* Name() { return "ScriptUrlSetTraits"; } |
51 | 197 |
52 static bool IsMatch(const Object& a, const Object& b) { | 198 static bool IsMatch(const Object& a, const Object& b) { |
53 if (!a.IsString() || !b.IsString()) { | 199 if (!a.IsString() || !b.IsString()) { |
54 return false; | 200 return false; |
55 } | 201 } |
56 | 202 |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
173 String::Handle(a_lib.IsNull() ? String::null() : a_lib.url()); | 319 String::Handle(a_lib.IsNull() ? String::null() : a_lib.url()); |
174 const String& b_lib_url = | 320 const String& b_lib_url = |
175 String::Handle(b_lib.IsNull() ? String::null() : b_lib.url()); | 321 String::Handle(b_lib.IsNull() ? String::null() : b_lib.url()); |
176 return a_lib_url.Equals(b_lib_url); | 322 return a_lib_url.Equals(b_lib_url); |
177 } | 323 } |
178 | 324 |
179 | 325 |
180 IsolateReloadContext::IsolateReloadContext(Isolate* isolate) | 326 IsolateReloadContext::IsolateReloadContext(Isolate* isolate) |
181 : start_time_micros_(OS::GetCurrentMonotonicMicros()), | 327 : start_time_micros_(OS::GetCurrentMonotonicMicros()), |
182 isolate_(isolate), | 328 isolate_(isolate), |
183 has_error_(false), | |
184 saved_num_cids_(-1), | 329 saved_num_cids_(-1), |
185 saved_class_table_(NULL), | 330 saved_class_table_(NULL), |
186 num_saved_libs_(-1), | 331 num_saved_libs_(-1), |
332 instance_morphers_(), | |
333 reasons_to_cancel_reload_(), | |
334 cid_mapper_(), | |
187 script_uri_(String::null()), | 335 script_uri_(String::null()), |
188 error_(Error::null()), | 336 error_(Error::null()), |
189 old_classes_set_storage_(Array::null()), | 337 old_classes_set_storage_(Array::null()), |
190 class_map_storage_(Array::null()), | 338 class_map_storage_(Array::null()), |
191 old_libraries_set_storage_(Array::null()), | 339 old_libraries_set_storage_(Array::null()), |
192 library_map_storage_(Array::null()), | 340 library_map_storage_(Array::null()), |
193 become_map_storage_(Array::null()), | 341 become_map_storage_(Array::null()), |
194 become_enum_mappings_(GrowableObjectArray::null()), | 342 become_enum_mappings_(GrowableObjectArray::null()), |
195 saved_root_library_(Library::null()), | 343 saved_root_library_(Library::null()), |
196 saved_libraries_(GrowableObjectArray::null()) { | 344 saved_libraries_(GrowableObjectArray::null()) { |
197 // NOTE: DO NOT ALLOCATE ANY RAW OBJECTS HERE. The IsolateReloadContext is not | 345 // NOTE: DO NOT ALLOCATE ANY RAW OBJECTS HERE. The IsolateReloadContext is not |
198 // associated with the isolate yet and if a GC is triggered here the raw | 346 // associated with the isolate yet and if a GC is triggered here the raw |
199 // objects will not be properly accounted for. | 347 // objects will not be properly accounted for. |
200 } | 348 } |
201 | 349 |
202 | 350 |
203 IsolateReloadContext::~IsolateReloadContext() { | 351 IsolateReloadContext::~IsolateReloadContext() { |
204 } | 352 } |
205 | 353 |
206 | 354 |
207 void IsolateReloadContext::ReportError(const Error& error) { | 355 void IsolateReloadContext::ReportError(const Error& error) { |
208 has_error_ = true; | |
209 error_ = error.raw(); | |
210 if (FLAG_trace_reload) { | 356 if (FLAG_trace_reload) { |
211 THR_Print("ISO-RELOAD: Error: %s\n", error.ToErrorCString()); | 357 THR_Print("ISO-RELOAD: Error: %s\n", error.ToErrorCString()); |
212 } | 358 } |
213 ServiceEvent service_event(I, ServiceEvent::kIsolateReload); | 359 ServiceEvent service_event(I, ServiceEvent::kIsolateReload); |
214 service_event.set_reload_error(&error); | 360 service_event.set_reload_error(&error); |
215 Service::HandleEvent(&service_event); | 361 Service::HandleEvent(&service_event); |
216 } | 362 } |
217 | 363 |
218 | 364 |
219 void IsolateReloadContext::ReportError(const String& error_msg) { | |
220 ReportError(LanguageError::Handle(LanguageError::New(error_msg))); | |
221 } | |
222 | |
223 | |
224 void IsolateReloadContext::ReportSuccess() { | 365 void IsolateReloadContext::ReportSuccess() { |
225 ServiceEvent service_event(I, ServiceEvent::kIsolateReload); | 366 ServiceEvent service_event(I, ServiceEvent::kIsolateReload); |
226 Service::HandleEvent(&service_event); | 367 Service::HandleEvent(&service_event); |
227 } | 368 } |
228 | 369 |
229 | 370 |
371 class Aborted : public ReasonForCancelling { | |
372 public: | |
373 explicit Aborted(const Error& error) | |
374 : ReasonForCancelling(), error_(error) { } | |
375 | |
376 private: | |
377 const Error& error_; | |
378 | |
379 RawError* ToError() { return error_.raw(); } | |
380 RawString* ToString() { | |
381 return String::NewFormatted("%s", error_.ToErrorCString()); | |
382 } | |
383 }; | |
384 | |
385 | |
230 void IsolateReloadContext::StartReload() { | 386 void IsolateReloadContext::StartReload() { |
231 TIMELINE_SCOPE(Reload); | 387 TIMELINE_SCOPE(Reload); |
232 Thread* thread = Thread::Current(); | 388 Thread* thread = Thread::Current(); |
233 ASSERT(isolate() == thread->isolate()); | 389 ASSERT(isolate() == thread->isolate()); |
234 | 390 |
235 // Grab root library before calling CheckpointBeforeReload. | 391 // Grab root library before calling CheckpointBeforeReload. |
236 const Library& root_lib = Library::Handle(object_store()->root_library()); | 392 const Library& root_lib = Library::Handle(object_store()->root_library()); |
237 ASSERT(!root_lib.IsNull()); | 393 ASSERT(!root_lib.IsNull()); |
238 const String& root_lib_url = String::Handle(root_lib.url()); | 394 const String& root_lib_url = String::Handle(root_lib.url()); |
239 | 395 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
274 TransitionVMToNative transition(thread); | 430 TransitionVMToNative transition(thread); |
275 Api::Scope api_scope(thread); | 431 Api::Scope api_scope(thread); |
276 | 432 |
277 Dart_Handle retval = | 433 Dart_Handle retval = |
278 (I->library_tag_handler())(Dart_kScriptTag, | 434 (I->library_tag_handler())(Dart_kScriptTag, |
279 Api::NewHandle(thread, Library::null()), | 435 Api::NewHandle(thread, Library::null()), |
280 Api::NewHandle(thread, root_lib_url.raw())); | 436 Api::NewHandle(thread, root_lib_url.raw())); |
281 result = Api::UnwrapHandle(retval); | 437 result = Api::UnwrapHandle(retval); |
282 } | 438 } |
283 if (result.IsError()) { | 439 if (result.IsError()) { |
284 ReportError(Error::Cast(result)); | 440 const Error& error = Error::Cast(result); |
441 AddReasonForCancelling(new Aborted(error)); | |
285 } | 442 } |
286 } | 443 } |
287 | 444 |
288 | 445 |
289 void IsolateReloadContext::RegisterClass(const Class& new_cls) { | 446 void IsolateReloadContext::RegisterClass(const Class& new_cls) { |
290 const Class& old_cls = Class::Handle(OldClassOrNull(new_cls)); | 447 const Class& old_cls = Class::Handle(OldClassOrNull(new_cls)); |
291 if (old_cls.IsNull()) { | 448 if (old_cls.IsNull()) { |
292 I->class_table()->Register(new_cls); | 449 I->class_table()->Register(new_cls); |
293 | 450 |
294 if (FLAG_identity_reload) { | 451 if (FLAG_identity_reload) { |
(...skipping 17 matching lines...) Expand all Loading... | |
312 } | 469 } |
313 | 470 |
314 | 471 |
315 void IsolateReloadContext::FinishReload() { | 472 void IsolateReloadContext::FinishReload() { |
316 BuildLibraryMapping(); | 473 BuildLibraryMapping(); |
317 TIR_Print("---- DONE FINALIZING\n"); | 474 TIR_Print("---- DONE FINALIZING\n"); |
318 if (ValidateReload()) { | 475 if (ValidateReload()) { |
319 Commit(); | 476 Commit(); |
320 PostCommit(); | 477 PostCommit(); |
321 } else { | 478 } else { |
479 ReportReasonsForCancelling(); | |
322 Rollback(); | 480 Rollback(); |
323 } | 481 } |
324 // ValidateReload mutates the direct subclass information and does | 482 // ValidateReload mutates the direct subclass information and does |
325 // not remove dead subclasses. Rebuild the direct subclass | 483 // not remove dead subclasses. Rebuild the direct subclass |
326 // information from scratch. | 484 // information from scratch. |
327 RebuildDirectSubclasses(); | 485 RebuildDirectSubclasses(); |
328 | 486 |
329 if (FLAG_write_protect_code) { | 487 if (FLAG_write_protect_code) { |
330 // Disable code page write protection while we are reloading. | 488 // Disable code page write protection while we are reloading. |
331 I->heap()->WriteProtectCode(true); | 489 I->heap()->WriteProtectCode(true); |
332 } | 490 } |
333 | 491 |
334 BackgroundCompiler::Enable(); | 492 BackgroundCompiler::Enable(); |
335 } | 493 } |
336 | 494 |
337 | 495 |
338 void IsolateReloadContext::AbortReload(const Error& error) { | 496 void IsolateReloadContext::AbortReload(const Error& error) { |
339 ReportError(error); | 497 AddReasonForCancelling(new Aborted(error)); |
498 ReportReasonsForCancelling(); | |
340 Rollback(); | 499 Rollback(); |
341 } | 500 } |
342 | 501 |
343 | 502 |
344 void IsolateReloadContext::EnsuredUnoptimizedCodeForStack() { | 503 void IsolateReloadContext::EnsuredUnoptimizedCodeForStack() { |
345 TIMELINE_SCOPE(EnsuredUnoptimizedCodeForStack); | 504 TIMELINE_SCOPE(EnsuredUnoptimizedCodeForStack); |
346 StackFrameIterator it(StackFrameIterator::kDontValidateFrames); | 505 StackFrameIterator it(StackFrameIterator::kDontValidateFrames); |
347 | 506 |
348 Function& func = Function::Handle(); | 507 Function& func = Function::Handle(); |
349 while (it.HasNextFrame()) { | 508 while (it.HasNextFrame()) { |
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
733 | 892 |
734 void IsolateReloadContext::PostCommit() { | 893 void IsolateReloadContext::PostCommit() { |
735 TIMELINE_SCOPE(PostCommit); | 894 TIMELINE_SCOPE(PostCommit); |
736 set_saved_root_library(Library::Handle()); | 895 set_saved_root_library(Library::Handle()); |
737 set_saved_libraries(GrowableObjectArray::Handle()); | 896 set_saved_libraries(GrowableObjectArray::Handle()); |
738 InvalidateWorld(); | 897 InvalidateWorld(); |
739 TIR_Print("---- DONE COMMIT\n"); | 898 TIR_Print("---- DONE COMMIT\n"); |
740 } | 899 } |
741 | 900 |
742 | 901 |
902 void IsolateReloadContext::AddReasonForCancelling(ReasonForCancelling* reason) { | |
903 reasons_to_cancel_reload_.Add(reason); | |
904 } | |
905 | |
906 | |
907 void IsolateReloadContext::AddInstanceMorpher(InstanceMorpher* morpher) { | |
908 instance_morphers_.Add(morpher); | |
909 cid_mapper_.Insert(morpher); | |
910 } | |
911 | |
912 | |
913 void IsolateReloadContext::ReportReasonsForCancelling() { | |
914 ASSERT(HasReasonsForCancelling()); | |
915 for (int i = 0; i < reasons_to_cancel_reload_.length(); i++) { | |
916 reasons_to_cancel_reload_.At(i)->Report(this); | |
917 } | |
918 } | |
919 | |
920 | |
921 // The ObjectLocator is used for collecting instances that | |
922 // needs to be morphed. | |
923 class ObjectLocator : public ObjectVisitor { | |
924 public: | |
925 explicit ObjectLocator(IsolateReloadContext* context) | |
926 : context_(context), count_(0) { | |
927 } | |
928 | |
929 void VisitObject(RawObject* obj) { | |
930 InstanceMorpher* morpher = | |
931 context_->cid_mapper_.LookupValue(obj->GetClassId()); | |
932 if (morpher != NULL) { | |
933 morpher->AddObject(obj); | |
934 count_++; | |
935 } | |
936 } | |
937 | |
938 // Return the number of located objects for morphing. | |
939 intptr_t count() { return count_; } | |
940 private: | |
941 IsolateReloadContext* context_; | |
942 intptr_t count_; | |
943 }; | |
944 | |
945 | |
946 void IsolateReloadContext::MorphInstances() { | |
947 ASSERT(HasInstanceMorphers()); | |
948 if (FLAG_trace_reload) { | |
949 OS::Print("MorphInstance: \n"); | |
Cutch
2016/07/26 14:42:45
Use TIR_Print (it checks FLAG_trace_reload for you
bakster
2016/07/26 16:54:51
Done.
| |
950 for (intptr_t i = 0; i < instance_morphers_.length(); i++) { | |
951 instance_morphers_.At(i)->Dump(); | |
952 } | |
953 } | |
954 | |
955 // Find all objects that need to be morphed. | |
956 ObjectLocator locator(this); | |
957 isolate()->heap()->VisitObjects(&locator); | |
958 | |
959 // Return if no objects are located. | |
960 intptr_t count = locator.count(); | |
961 if (count == 0) return; | |
962 | |
963 if (FLAG_trace_reload) { | |
964 OS::Print("Found %" Pd " object%s subject to morphing.\n", | |
Cutch
2016/07/26 14:42:45
TIR_Print
bakster
2016/07/26 16:54:51
Done.
| |
965 count, (count > 1) ? "s" : ""); | |
966 } | |
967 | |
968 Array& before = Array::Handle(); | |
969 Array& after = Array::Handle(); | |
970 { // Prevent GC to take place due object format confusion. | |
971 // Hint: More than one class share the same cid. | |
972 NoHeapGrowthControlScope scope; | |
973 for (intptr_t i = 0; i < instance_morphers_.length(); i++) { | |
974 instance_morphers_.At(i)->CreateMorphedCopies(); | |
975 } | |
976 // Create the inputs for Become. | |
977 intptr_t index = 0; | |
978 before = Array::New(count); | |
979 after = Array::New(count); | |
980 for (intptr_t i = 0; i < instance_morphers_.length(); i++) { | |
981 InstanceMorpher* morpher = instance_morphers_.At(i); | |
982 for (intptr_t j = 0; j < morpher->before()->length(); j++) { | |
983 before.SetAt(index, *morpher->before()->At(j)); | |
984 after.SetAt(index, *morpher->after()->At(j)); | |
985 index++; | |
986 } | |
987 } | |
988 ASSERT(index == count); | |
989 } | |
990 | |
991 // This is important: The saved class table (describing before objects) | |
992 // must be zapped to prevent the forwarding in GetClassForHeapWalkAt. | |
993 // Instance will from now be described by the isolate's class table. | |
994 free(saved_class_table_); | |
995 saved_class_table_ = NULL; | |
996 Become::ElementsForwardIdentity(before, after); | |
997 } | |
998 | |
999 | |
743 bool IsolateReloadContext::ValidateReload() { | 1000 bool IsolateReloadContext::ValidateReload() { |
744 TIMELINE_SCOPE(ValidateReload); | 1001 TIMELINE_SCOPE(ValidateReload); |
745 if (has_error_) { | 1002 if (has_error()) return false; |
746 return false; | |
747 } | |
748 | 1003 |
749 // Validate libraries. | 1004 // Validate libraries. |
750 { | 1005 { |
751 ASSERT(library_map_storage_ != Array::null()); | 1006 ASSERT(library_map_storage_ != Array::null()); |
752 UnorderedHashMap<LibraryMapTraits> map(library_map_storage_); | 1007 UnorderedHashMap<LibraryMapTraits> map(library_map_storage_); |
753 UnorderedHashMap<LibraryMapTraits>::Iterator it(&map); | 1008 UnorderedHashMap<LibraryMapTraits>::Iterator it(&map); |
754 Library& lib = Library::Handle(); | 1009 Library& lib = Library::Handle(); |
755 Library& new_lib = Library::Handle(); | 1010 Library& new_lib = Library::Handle(); |
756 while (it.MoveNext()) { | 1011 while (it.MoveNext()) { |
757 const intptr_t entry = it.Current(); | 1012 const intptr_t entry = it.Current(); |
758 new_lib = Library::RawCast(map.GetKey(entry)); | 1013 new_lib = Library::RawCast(map.GetKey(entry)); |
759 lib = Library::RawCast(map.GetPayload(entry, 0)); | 1014 lib = Library::RawCast(map.GetPayload(entry, 0)); |
760 if (new_lib.raw() != lib.raw()) { | 1015 if (new_lib.raw() != lib.raw()) { |
761 if (!lib.CanReload(new_lib)) { | 1016 lib.CheckReload(new_lib, this); |
762 map.Release(); | |
763 return false; | |
764 } | |
765 } | 1017 } |
766 } | 1018 } |
767 map.Release(); | 1019 map.Release(); |
768 } | 1020 } |
769 | 1021 |
770 // Validate classes. | 1022 // Validate classes. |
771 { | 1023 { |
772 ASSERT(class_map_storage_ != Array::null()); | 1024 ASSERT(class_map_storage_ != Array::null()); |
773 UnorderedHashMap<ClassMapTraits> map(class_map_storage_); | 1025 UnorderedHashMap<ClassMapTraits> map(class_map_storage_); |
774 UnorderedHashMap<ClassMapTraits>::Iterator it(&map); | 1026 UnorderedHashMap<ClassMapTraits>::Iterator it(&map); |
775 Class& cls = Class::Handle(); | 1027 Class& cls = Class::Handle(); |
776 Class& new_cls = Class::Handle(); | 1028 Class& new_cls = Class::Handle(); |
777 while (it.MoveNext()) { | 1029 while (it.MoveNext()) { |
778 const intptr_t entry = it.Current(); | 1030 const intptr_t entry = it.Current(); |
779 new_cls = Class::RawCast(map.GetKey(entry)); | 1031 new_cls = Class::RawCast(map.GetKey(entry)); |
780 cls = Class::RawCast(map.GetPayload(entry, 0)); | 1032 cls = Class::RawCast(map.GetPayload(entry, 0)); |
781 if (new_cls.raw() != cls.raw()) { | 1033 if (new_cls.raw() != cls.raw()) { |
782 if (!cls.CanReload(new_cls)) { | 1034 cls.CheckReload(new_cls, this); |
783 map.Release(); | |
784 return false; | |
785 } | |
786 } | 1035 } |
787 } | 1036 } |
788 map.Release(); | 1037 map.Release(); |
789 } | 1038 } |
790 return true; | 1039 |
1040 // Perform shape shifting of instances if necessary. | |
1041 if (HasInstanceMorphers()) { | |
Cutch
2016/07/26 14:42:45
This should be done in the commit path
bakster
2016/07/26 16:54:51
Done.
| |
1042 MorphInstances(); | |
1043 } | |
1044 | |
1045 return !HasReasonsForCancelling(); | |
791 } | 1046 } |
792 | 1047 |
793 | 1048 |
794 RawClass* IsolateReloadContext::FindOriginalClass(const Class& cls) { | 1049 RawClass* IsolateReloadContext::FindOriginalClass(const Class& cls) { |
795 return MappedClass(cls); | 1050 return MappedClass(cls); |
796 } | 1051 } |
797 | 1052 |
798 | 1053 |
799 RawClass* IsolateReloadContext::GetClassForHeapWalkAt(intptr_t cid) { | 1054 RawClass* IsolateReloadContext::GetClassForHeapWalkAt(intptr_t cid) { |
800 if (saved_class_table_ != NULL) { | 1055 if (saved_class_table_ != NULL) { |
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1131 ASSERT(!super_cls.IsNull()); | 1386 ASSERT(!super_cls.IsNull()); |
1132 super_cls.AddDirectSubclass(cls); | 1387 super_cls.AddDirectSubclass(cls); |
1133 } | 1388 } |
1134 } | 1389 } |
1135 } | 1390 } |
1136 } | 1391 } |
1137 | 1392 |
1138 #endif // !PRODUCT | 1393 #endif // !PRODUCT |
1139 | 1394 |
1140 } // namespace dart | 1395 } // namespace dart |
OLD | NEW |