Chromium Code Reviews| 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 LogBlock blocker; | |
|
Cutch
2016/07/26 17:10:16
Remove this LogBlock -- the one in Dump should be
bakster
2016/07/26 18:01:47
Done.
| |
| 130 THR_Print("%s\n", cls.ToCString()); | |
| 131 if (cls.NumTypeArguments()) { | |
| 132 intptr_t field_offset = cls.type_arguments_field_offset(); | |
| 133 ASSERT(field_offset != Class::kNoTypeArguments); | |
| 134 THR_Print(" - @%" Pd " <type arguments>\n", field_offset); | |
| 135 } | |
| 136 const Array& fields = Array::Handle(cls.OffsetToFieldMap()); | |
| 137 Field& field = Field::Handle(); | |
| 138 String& name = String::Handle(); | |
| 139 for (intptr_t i = 0; i < fields.Length(); i++) { | |
| 140 if (fields.At(i) != Field::null()) { | |
| 141 field = Field::RawCast(fields.At(i)); | |
| 142 ASSERT(field.is_instance()); | |
| 143 name = field.name(); | |
| 144 THR_Print(" - @%" Pd " %s\n", field.Offset(), name.ToCString()); | |
| 145 } | |
| 146 } | |
| 147 | |
| 148 THR_Print("Mapping: "); | |
| 149 for (int i = 0; i < mapping_.length(); i +=2) { | |
| 150 THR_Print(" %" Pd "->%" Pd, mapping_.At(i), mapping_.At(i+1)); | |
| 151 } | |
| 152 THR_Print("\n"); | |
| 153 } | |
| 154 | |
| 155 | |
| 156 void InstanceMorpher::Dump() const { | |
| 157 LogBlock blocker; | |
| 158 THR_Print("Morphing from "); | |
| 159 DumpFormatFor(from_); | |
| 160 THR_Print("To "); | |
| 161 DumpFormatFor(to_); | |
| 162 THR_Print("\n"); | |
| 163 } | |
| 164 | |
| 165 | |
| 166 void ReasonForCancelling::Report(IsolateReloadContext* context) { | |
| 167 const Error& error = Error::Handle(ToError()); | |
| 168 context->ReportError(error); | |
| 169 } | |
| 170 | |
| 171 | |
| 172 RawError* ReasonForCancelling::ToError() { | |
| 173 // By default create the error returned from ToString. | |
| 174 const String& message = String::Handle(ToString()); | |
| 175 return LanguageError::New(message); | |
| 176 } | |
| 177 | |
| 178 | |
| 179 RawString* ReasonForCancelling::ToString() { | |
| 180 UNREACHABLE(); | |
| 181 return NULL; | |
| 182 } | |
| 183 | |
| 184 | |
| 185 RawError* IsolateReloadContext::error() const { | |
| 186 ASSERT(has_error()); | |
| 187 // Report the first error to the surroundings. | |
| 188 const Error& error = | |
| 189 Error::Handle(reasons_to_cancel_reload_.At(0)->ToError()); | |
| 190 OS::Print("[[%s]]\n", error.ToCString()); | |
| 191 return error.raw(); | |
| 192 } | |
| 193 | |
| 47 class ScriptUrlSetTraits { | 194 class ScriptUrlSetTraits { |
| 48 public: | 195 public: |
| 49 static bool ReportStats() { return false; } | 196 static bool ReportStats() { return false; } |
| 50 static const char* Name() { return "ScriptUrlSetTraits"; } | 197 static const char* Name() { return "ScriptUrlSetTraits"; } |
| 51 | 198 |
| 52 static bool IsMatch(const Object& a, const Object& b) { | 199 static bool IsMatch(const Object& a, const Object& b) { |
| 53 if (!a.IsString() || !b.IsString()) { | 200 if (!a.IsString() || !b.IsString()) { |
| 54 return false; | 201 return false; |
| 55 } | 202 } |
| 56 | 203 |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 173 String::Handle(a_lib.IsNull() ? String::null() : a_lib.url()); | 320 String::Handle(a_lib.IsNull() ? String::null() : a_lib.url()); |
| 174 const String& b_lib_url = | 321 const String& b_lib_url = |
| 175 String::Handle(b_lib.IsNull() ? String::null() : b_lib.url()); | 322 String::Handle(b_lib.IsNull() ? String::null() : b_lib.url()); |
| 176 return a_lib_url.Equals(b_lib_url); | 323 return a_lib_url.Equals(b_lib_url); |
| 177 } | 324 } |
| 178 | 325 |
| 179 | 326 |
| 180 IsolateReloadContext::IsolateReloadContext(Isolate* isolate) | 327 IsolateReloadContext::IsolateReloadContext(Isolate* isolate) |
| 181 : start_time_micros_(OS::GetCurrentMonotonicMicros()), | 328 : start_time_micros_(OS::GetCurrentMonotonicMicros()), |
| 182 isolate_(isolate), | 329 isolate_(isolate), |
| 183 has_error_(false), | |
| 184 saved_num_cids_(-1), | 330 saved_num_cids_(-1), |
| 185 saved_class_table_(NULL), | 331 saved_class_table_(NULL), |
| 186 num_saved_libs_(-1), | 332 num_saved_libs_(-1), |
| 333 instance_morphers_(), | |
| 334 reasons_to_cancel_reload_(), | |
| 335 cid_mapper_(), | |
| 187 script_uri_(String::null()), | 336 script_uri_(String::null()), |
| 188 error_(Error::null()), | 337 error_(Error::null()), |
| 189 old_classes_set_storage_(Array::null()), | 338 old_classes_set_storage_(Array::null()), |
| 190 class_map_storage_(Array::null()), | 339 class_map_storage_(Array::null()), |
| 191 old_libraries_set_storage_(Array::null()), | 340 old_libraries_set_storage_(Array::null()), |
| 192 library_map_storage_(Array::null()), | 341 library_map_storage_(Array::null()), |
| 193 become_map_storage_(Array::null()), | 342 become_map_storage_(Array::null()), |
| 194 become_enum_mappings_(GrowableObjectArray::null()), | 343 become_enum_mappings_(GrowableObjectArray::null()), |
| 195 saved_root_library_(Library::null()), | 344 saved_root_library_(Library::null()), |
| 196 saved_libraries_(GrowableObjectArray::null()) { | 345 saved_libraries_(GrowableObjectArray::null()) { |
| 197 // NOTE: DO NOT ALLOCATE ANY RAW OBJECTS HERE. The IsolateReloadContext is not | 346 // 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 | 347 // associated with the isolate yet and if a GC is triggered here the raw |
| 199 // objects will not be properly accounted for. | 348 // objects will not be properly accounted for. |
| 200 } | 349 } |
| 201 | 350 |
| 202 | 351 |
| 203 IsolateReloadContext::~IsolateReloadContext() { | 352 IsolateReloadContext::~IsolateReloadContext() { |
| 204 } | 353 } |
| 205 | 354 |
| 206 | 355 |
| 207 void IsolateReloadContext::ReportError(const Error& error) { | 356 void IsolateReloadContext::ReportError(const Error& error) { |
| 208 has_error_ = true; | |
| 209 error_ = error.raw(); | |
| 210 if (FLAG_trace_reload) { | 357 if (FLAG_trace_reload) { |
| 211 THR_Print("ISO-RELOAD: Error: %s\n", error.ToErrorCString()); | 358 THR_Print("ISO-RELOAD: Error: %s\n", error.ToErrorCString()); |
| 212 } | 359 } |
| 213 ServiceEvent service_event(I, ServiceEvent::kIsolateReload); | 360 ServiceEvent service_event(I, ServiceEvent::kIsolateReload); |
| 214 service_event.set_reload_error(&error); | 361 service_event.set_reload_error(&error); |
| 215 Service::HandleEvent(&service_event); | 362 Service::HandleEvent(&service_event); |
| 216 } | 363 } |
| 217 | 364 |
| 218 | 365 |
| 219 void IsolateReloadContext::ReportError(const String& error_msg) { | |
| 220 ReportError(LanguageError::Handle(LanguageError::New(error_msg))); | |
| 221 } | |
| 222 | |
| 223 | |
| 224 void IsolateReloadContext::ReportSuccess() { | 366 void IsolateReloadContext::ReportSuccess() { |
| 225 ServiceEvent service_event(I, ServiceEvent::kIsolateReload); | 367 ServiceEvent service_event(I, ServiceEvent::kIsolateReload); |
| 226 Service::HandleEvent(&service_event); | 368 Service::HandleEvent(&service_event); |
| 227 } | 369 } |
| 228 | 370 |
| 229 | 371 |
| 372 class Aborted : public ReasonForCancelling { | |
| 373 public: | |
| 374 explicit Aborted(const Error& error) | |
| 375 : ReasonForCancelling(), error_(error) { } | |
| 376 | |
| 377 private: | |
| 378 const Error& error_; | |
| 379 | |
| 380 RawError* ToError() { return error_.raw(); } | |
| 381 RawString* ToString() { | |
| 382 return String::NewFormatted("%s", error_.ToErrorCString()); | |
| 383 } | |
| 384 }; | |
| 385 | |
| 386 | |
| 230 void IsolateReloadContext::StartReload() { | 387 void IsolateReloadContext::StartReload() { |
| 231 TIMELINE_SCOPE(Reload); | 388 TIMELINE_SCOPE(Reload); |
| 232 Thread* thread = Thread::Current(); | 389 Thread* thread = Thread::Current(); |
| 233 ASSERT(isolate() == thread->isolate()); | 390 ASSERT(isolate() == thread->isolate()); |
| 234 | 391 |
| 235 // Grab root library before calling CheckpointBeforeReload. | 392 // Grab root library before calling CheckpointBeforeReload. |
| 236 const Library& root_lib = Library::Handle(object_store()->root_library()); | 393 const Library& root_lib = Library::Handle(object_store()->root_library()); |
| 237 ASSERT(!root_lib.IsNull()); | 394 ASSERT(!root_lib.IsNull()); |
| 238 const String& root_lib_url = String::Handle(root_lib.url()); | 395 const String& root_lib_url = String::Handle(root_lib.url()); |
| 239 | 396 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 274 TransitionVMToNative transition(thread); | 431 TransitionVMToNative transition(thread); |
| 275 Api::Scope api_scope(thread); | 432 Api::Scope api_scope(thread); |
| 276 | 433 |
| 277 Dart_Handle retval = | 434 Dart_Handle retval = |
| 278 (I->library_tag_handler())(Dart_kScriptTag, | 435 (I->library_tag_handler())(Dart_kScriptTag, |
| 279 Api::NewHandle(thread, Library::null()), | 436 Api::NewHandle(thread, Library::null()), |
| 280 Api::NewHandle(thread, root_lib_url.raw())); | 437 Api::NewHandle(thread, root_lib_url.raw())); |
| 281 result = Api::UnwrapHandle(retval); | 438 result = Api::UnwrapHandle(retval); |
| 282 } | 439 } |
| 283 if (result.IsError()) { | 440 if (result.IsError()) { |
| 284 ReportError(Error::Cast(result)); | 441 const Error& error = Error::Cast(result); |
| 442 AddReasonForCancelling(new Aborted(error)); | |
| 285 } | 443 } |
| 286 } | 444 } |
| 287 | 445 |
| 288 | 446 |
| 289 void IsolateReloadContext::RegisterClass(const Class& new_cls) { | 447 void IsolateReloadContext::RegisterClass(const Class& new_cls) { |
| 290 const Class& old_cls = Class::Handle(OldClassOrNull(new_cls)); | 448 const Class& old_cls = Class::Handle(OldClassOrNull(new_cls)); |
| 291 if (old_cls.IsNull()) { | 449 if (old_cls.IsNull()) { |
| 292 I->class_table()->Register(new_cls); | 450 I->class_table()->Register(new_cls); |
| 293 | 451 |
| 294 if (FLAG_identity_reload) { | 452 if (FLAG_identity_reload) { |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 312 } | 470 } |
| 313 | 471 |
| 314 | 472 |
| 315 void IsolateReloadContext::FinishReload() { | 473 void IsolateReloadContext::FinishReload() { |
| 316 BuildLibraryMapping(); | 474 BuildLibraryMapping(); |
| 317 TIR_Print("---- DONE FINALIZING\n"); | 475 TIR_Print("---- DONE FINALIZING\n"); |
| 318 if (ValidateReload()) { | 476 if (ValidateReload()) { |
| 319 Commit(); | 477 Commit(); |
| 320 PostCommit(); | 478 PostCommit(); |
| 321 } else { | 479 } else { |
| 480 ReportReasonsForCancelling(); | |
| 322 Rollback(); | 481 Rollback(); |
| 323 } | 482 } |
| 324 // ValidateReload mutates the direct subclass information and does | 483 // ValidateReload mutates the direct subclass information and does |
| 325 // not remove dead subclasses. Rebuild the direct subclass | 484 // not remove dead subclasses. Rebuild the direct subclass |
| 326 // information from scratch. | 485 // information from scratch. |
| 327 RebuildDirectSubclasses(); | 486 RebuildDirectSubclasses(); |
| 328 | 487 |
| 329 if (FLAG_write_protect_code) { | 488 if (FLAG_write_protect_code) { |
| 330 // Disable code page write protection while we are reloading. | 489 // Disable code page write protection while we are reloading. |
| 331 I->heap()->WriteProtectCode(true); | 490 I->heap()->WriteProtectCode(true); |
| 332 } | 491 } |
| 333 | 492 |
| 334 BackgroundCompiler::Enable(); | 493 BackgroundCompiler::Enable(); |
| 335 } | 494 } |
| 336 | 495 |
| 337 | 496 |
| 338 void IsolateReloadContext::AbortReload(const Error& error) { | 497 void IsolateReloadContext::AbortReload(const Error& error) { |
| 339 ReportError(error); | 498 AddReasonForCancelling(new Aborted(error)); |
| 499 ReportReasonsForCancelling(); | |
| 340 Rollback(); | 500 Rollback(); |
| 341 } | 501 } |
| 342 | 502 |
| 343 | 503 |
| 344 void IsolateReloadContext::EnsuredUnoptimizedCodeForStack() { | 504 void IsolateReloadContext::EnsuredUnoptimizedCodeForStack() { |
| 345 TIMELINE_SCOPE(EnsuredUnoptimizedCodeForStack); | 505 TIMELINE_SCOPE(EnsuredUnoptimizedCodeForStack); |
| 346 StackFrameIterator it(StackFrameIterator::kDontValidateFrames); | 506 StackFrameIterator it(StackFrameIterator::kDontValidateFrames); |
| 347 | 507 |
| 348 Function& func = Function::Handle(); | 508 Function& func = Function::Handle(); |
| 349 while (it.HasNextFrame()) { | 509 while (it.HasNextFrame()) { |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 578 class_map.Release(); | 738 class_map.Release(); |
| 579 reverse_class_map.Release(); | 739 reverse_class_map.Release(); |
| 580 } | 740 } |
| 581 #endif | 741 #endif |
| 582 | 742 |
| 583 | 743 |
| 584 void IsolateReloadContext::Commit() { | 744 void IsolateReloadContext::Commit() { |
| 585 TIMELINE_SCOPE(Commit); | 745 TIMELINE_SCOPE(Commit); |
| 586 TIR_Print("---- COMMITTING REVERSE MAP\n"); | 746 TIR_Print("---- COMMITTING REVERSE MAP\n"); |
| 587 | 747 |
| 748 // Perform shape shifting of instances if necessary. | |
| 749 if (HasInstanceMorphers()) { | |
| 750 MorphInstances(); | |
|
Cutch
2016/07/26 17:10:16
Calling MorphInstances resets the saved_class_tabl
bakster
2016/07/26 18:01:47
The placement will be documents.
| |
| 751 } | |
| 752 | |
| 588 #ifdef DEBUG | 753 #ifdef DEBUG |
| 589 VerifyMaps(); | 754 VerifyMaps(); |
| 590 #endif | 755 #endif |
| 591 | 756 |
| 592 { | 757 { |
| 593 TIMELINE_SCOPE(CopyStaticFieldsAndPatchFieldsAndFunctions); | 758 TIMELINE_SCOPE(CopyStaticFieldsAndPatchFieldsAndFunctions); |
| 594 // Copy static field values from the old classes to the new classes. | 759 // Copy static field values from the old classes to the new classes. |
| 595 // Patch fields and functions in the old classes so that they retain | 760 // Patch fields and functions in the old classes so that they retain |
| 596 // the old script. | 761 // the old script. |
| 597 Class& cls = Class::Handle(); | 762 Class& cls = Class::Handle(); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 659 } | 824 } |
| 660 | 825 |
| 661 // Initialize library side table. | 826 // Initialize library side table. |
| 662 library_infos_.SetLength(libs.Length()); | 827 library_infos_.SetLength(libs.Length()); |
| 663 for (intptr_t i = 0; i < libs.Length(); i++) { | 828 for (intptr_t i = 0; i < libs.Length(); i++) { |
| 664 lib = Library::RawCast(libs.At(i)); | 829 lib = Library::RawCast(libs.At(i)); |
| 665 // Mark the library dirty if it comes after the libraries we saved. | 830 // Mark the library dirty if it comes after the libraries we saved. |
| 666 library_infos_[i].dirty = i >= num_saved_libs_; | 831 library_infos_[i].dirty = i >= num_saved_libs_; |
| 667 } | 832 } |
| 668 } | 833 } |
| 669 | 834 |
|
Cutch
2016/07/26 17:10:16
call MorphInstances here instead
bakster
2016/07/26 18:01:47
Acknowledged.
| |
| 670 { | 835 { |
| 671 const GrowableObjectArray& become_enum_mappings = | 836 const GrowableObjectArray& become_enum_mappings = |
| 672 GrowableObjectArray::Handle(become_enum_mappings_); | 837 GrowableObjectArray::Handle(become_enum_mappings_); |
| 673 UnorderedHashMap<BecomeMapTraits> become_map(become_map_storage_); | 838 UnorderedHashMap<BecomeMapTraits> become_map(become_map_storage_); |
| 674 intptr_t replacement_count = become_map.NumOccupied() + | 839 intptr_t replacement_count = become_map.NumOccupied() + |
| 675 become_enum_mappings.Length() / 2; | 840 become_enum_mappings.Length() / 2; |
| 676 const Array& before = | 841 const Array& before = |
| 677 Array::Handle(Array::New(replacement_count, Heap::kOld)); | 842 Array::Handle(Array::New(replacement_count, Heap::kOld)); |
| 678 const Array& after = | 843 const Array& after = |
| 679 Array::Handle(Array::New(replacement_count, Heap::kOld)); | 844 Array::Handle(Array::New(replacement_count, Heap::kOld)); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 733 | 898 |
| 734 void IsolateReloadContext::PostCommit() { | 899 void IsolateReloadContext::PostCommit() { |
| 735 TIMELINE_SCOPE(PostCommit); | 900 TIMELINE_SCOPE(PostCommit); |
| 736 set_saved_root_library(Library::Handle()); | 901 set_saved_root_library(Library::Handle()); |
| 737 set_saved_libraries(GrowableObjectArray::Handle()); | 902 set_saved_libraries(GrowableObjectArray::Handle()); |
| 738 InvalidateWorld(); | 903 InvalidateWorld(); |
| 739 TIR_Print("---- DONE COMMIT\n"); | 904 TIR_Print("---- DONE COMMIT\n"); |
| 740 } | 905 } |
| 741 | 906 |
| 742 | 907 |
| 908 void IsolateReloadContext::AddReasonForCancelling(ReasonForCancelling* reason) { | |
| 909 reasons_to_cancel_reload_.Add(reason); | |
| 910 } | |
| 911 | |
| 912 | |
| 913 void IsolateReloadContext::AddInstanceMorpher(InstanceMorpher* morpher) { | |
| 914 instance_morphers_.Add(morpher); | |
| 915 cid_mapper_.Insert(morpher); | |
| 916 } | |
| 917 | |
| 918 | |
| 919 void IsolateReloadContext::ReportReasonsForCancelling() { | |
| 920 ASSERT(HasReasonsForCancelling()); | |
| 921 for (int i = 0; i < reasons_to_cancel_reload_.length(); i++) { | |
| 922 reasons_to_cancel_reload_.At(i)->Report(this); | |
| 923 } | |
| 924 } | |
| 925 | |
| 926 | |
| 927 // The ObjectLocator is used for collecting instances that | |
| 928 // needs to be morphed. | |
| 929 class ObjectLocator : public ObjectVisitor { | |
| 930 public: | |
| 931 explicit ObjectLocator(IsolateReloadContext* context) | |
| 932 : context_(context), count_(0) { | |
| 933 } | |
| 934 | |
| 935 void VisitObject(RawObject* obj) { | |
| 936 InstanceMorpher* morpher = | |
| 937 context_->cid_mapper_.LookupValue(obj->GetClassId()); | |
| 938 if (morpher != NULL) { | |
| 939 morpher->AddObject(obj); | |
| 940 count_++; | |
| 941 } | |
| 942 } | |
| 943 | |
| 944 // Return the number of located objects for morphing. | |
| 945 intptr_t count() { return count_; } | |
| 946 private: | |
|
Cutch
2016/07/26 17:10:16
blank line between count() and private:
bakster
2016/07/26 18:01:47
Done.
| |
| 947 IsolateReloadContext* context_; | |
| 948 intptr_t count_; | |
| 949 }; | |
| 950 | |
| 951 | |
| 952 void IsolateReloadContext::MorphInstances() { | |
| 953 TIMELINE_SCOPE(MorphInstances); | |
| 954 ASSERT(HasInstanceMorphers()); | |
| 955 if (FLAG_trace_reload) { | |
| 956 LogBlock blocker; | |
| 957 TIR_Print("MorphInstance: \n"); | |
| 958 for (intptr_t i = 0; i < instance_morphers_.length(); i++) { | |
| 959 instance_morphers_.At(i)->Dump(); | |
| 960 } | |
| 961 } | |
| 962 | |
| 963 // Find all objects that need to be morphed. | |
| 964 ObjectLocator locator(this); | |
| 965 isolate()->heap()->VisitObjects(&locator); | |
| 966 | |
| 967 // Return if no objects are located. | |
| 968 intptr_t count = locator.count(); | |
| 969 if (count == 0) return; | |
| 970 | |
| 971 TIR_Print("Found %" Pd " object%s subject to morphing.\n", | |
| 972 count, (count > 1) ? "s" : ""); | |
| 973 | |
| 974 Array& before = Array::Handle(); | |
| 975 Array& after = Array::Handle(); | |
| 976 { // Prevent GC to take place due object format confusion. | |
| 977 // Hint: More than one class share the same cid. | |
| 978 NoHeapGrowthControlScope scope; | |
| 979 for (intptr_t i = 0; i < instance_morphers_.length(); i++) { | |
| 980 instance_morphers_.At(i)->CreateMorphedCopies(); | |
| 981 } | |
| 982 // Create the inputs for Become. | |
| 983 intptr_t index = 0; | |
| 984 before = Array::New(count); | |
| 985 after = Array::New(count); | |
| 986 for (intptr_t i = 0; i < instance_morphers_.length(); i++) { | |
| 987 InstanceMorpher* morpher = instance_morphers_.At(i); | |
| 988 for (intptr_t j = 0; j < morpher->before()->length(); j++) { | |
| 989 before.SetAt(index, *morpher->before()->At(j)); | |
| 990 after.SetAt(index, *morpher->after()->At(j)); | |
| 991 index++; | |
| 992 } | |
| 993 } | |
| 994 ASSERT(index == count); | |
| 995 } | |
| 996 | |
| 997 // This is important: The saved class table (describing before objects) | |
| 998 // must be zapped to prevent the forwarding in GetClassForHeapWalkAt. | |
| 999 // Instance will from now be described by the isolate's class table. | |
| 1000 free(saved_class_table_); | |
| 1001 saved_class_table_ = NULL; | |
| 1002 Become::ElementsForwardIdentity(before, after); | |
| 1003 } | |
| 1004 | |
| 1005 | |
| 743 bool IsolateReloadContext::ValidateReload() { | 1006 bool IsolateReloadContext::ValidateReload() { |
| 744 TIMELINE_SCOPE(ValidateReload); | 1007 TIMELINE_SCOPE(ValidateReload); |
| 745 if (has_error_) { | 1008 if (has_error()) return false; |
| 746 return false; | |
| 747 } | |
| 748 | 1009 |
| 749 // Validate libraries. | 1010 // Validate libraries. |
| 750 { | 1011 { |
| 751 ASSERT(library_map_storage_ != Array::null()); | 1012 ASSERT(library_map_storage_ != Array::null()); |
| 752 UnorderedHashMap<LibraryMapTraits> map(library_map_storage_); | 1013 UnorderedHashMap<LibraryMapTraits> map(library_map_storage_); |
| 753 UnorderedHashMap<LibraryMapTraits>::Iterator it(&map); | 1014 UnorderedHashMap<LibraryMapTraits>::Iterator it(&map); |
| 754 Library& lib = Library::Handle(); | 1015 Library& lib = Library::Handle(); |
| 755 Library& new_lib = Library::Handle(); | 1016 Library& new_lib = Library::Handle(); |
| 756 while (it.MoveNext()) { | 1017 while (it.MoveNext()) { |
| 757 const intptr_t entry = it.Current(); | 1018 const intptr_t entry = it.Current(); |
| 758 new_lib = Library::RawCast(map.GetKey(entry)); | 1019 new_lib = Library::RawCast(map.GetKey(entry)); |
| 759 lib = Library::RawCast(map.GetPayload(entry, 0)); | 1020 lib = Library::RawCast(map.GetPayload(entry, 0)); |
| 760 if (new_lib.raw() != lib.raw()) { | 1021 if (new_lib.raw() != lib.raw()) { |
| 761 if (!lib.CanReload(new_lib)) { | 1022 lib.CheckReload(new_lib, this); |
| 762 map.Release(); | |
| 763 return false; | |
| 764 } | |
| 765 } | 1023 } |
| 766 } | 1024 } |
| 767 map.Release(); | 1025 map.Release(); |
| 768 } | 1026 } |
| 769 | 1027 |
| 770 // Validate classes. | 1028 // Validate classes. |
| 771 { | 1029 { |
| 772 ASSERT(class_map_storage_ != Array::null()); | 1030 ASSERT(class_map_storage_ != Array::null()); |
| 773 UnorderedHashMap<ClassMapTraits> map(class_map_storage_); | 1031 UnorderedHashMap<ClassMapTraits> map(class_map_storage_); |
| 774 UnorderedHashMap<ClassMapTraits>::Iterator it(&map); | 1032 UnorderedHashMap<ClassMapTraits>::Iterator it(&map); |
| 775 Class& cls = Class::Handle(); | 1033 Class& cls = Class::Handle(); |
| 776 Class& new_cls = Class::Handle(); | 1034 Class& new_cls = Class::Handle(); |
| 777 while (it.MoveNext()) { | 1035 while (it.MoveNext()) { |
| 778 const intptr_t entry = it.Current(); | 1036 const intptr_t entry = it.Current(); |
| 779 new_cls = Class::RawCast(map.GetKey(entry)); | 1037 new_cls = Class::RawCast(map.GetKey(entry)); |
| 780 cls = Class::RawCast(map.GetPayload(entry, 0)); | 1038 cls = Class::RawCast(map.GetPayload(entry, 0)); |
| 781 if (new_cls.raw() != cls.raw()) { | 1039 if (new_cls.raw() != cls.raw()) { |
| 782 if (!cls.CanReload(new_cls)) { | 1040 cls.CheckReload(new_cls, this); |
| 783 map.Release(); | |
| 784 return false; | |
| 785 } | |
| 786 } | 1041 } |
| 787 } | 1042 } |
| 788 map.Release(); | 1043 map.Release(); |
| 789 } | 1044 } |
| 790 return true; | 1045 |
| 1046 return !HasReasonsForCancelling(); | |
| 791 } | 1047 } |
| 792 | 1048 |
| 793 | 1049 |
| 794 RawClass* IsolateReloadContext::FindOriginalClass(const Class& cls) { | 1050 RawClass* IsolateReloadContext::FindOriginalClass(const Class& cls) { |
| 795 return MappedClass(cls); | 1051 return MappedClass(cls); |
| 796 } | 1052 } |
| 797 | 1053 |
| 798 | 1054 |
| 799 RawClass* IsolateReloadContext::GetClassForHeapWalkAt(intptr_t cid) { | 1055 RawClass* IsolateReloadContext::GetClassForHeapWalkAt(intptr_t cid) { |
| 800 if (saved_class_table_ != NULL) { | 1056 if (saved_class_table_ != NULL) { |
| (...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1131 ASSERT(!super_cls.IsNull()); | 1387 ASSERT(!super_cls.IsNull()); |
| 1132 super_cls.AddDirectSubclass(cls); | 1388 super_cls.AddDirectSubclass(cls); |
| 1133 } | 1389 } |
| 1134 } | 1390 } |
| 1135 } | 1391 } |
| 1136 } | 1392 } |
| 1137 | 1393 |
| 1138 #endif // !PRODUCT | 1394 #endif // !PRODUCT |
| 1139 | 1395 |
| 1140 } // namespace dart | 1396 } // namespace dart |
| OLD | NEW |