| 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" |
| 11 #include "vm/hash_table.h" | 11 #include "vm/hash_table.h" |
| 12 #include "vm/isolate.h" | 12 #include "vm/isolate.h" |
| 13 #include "vm/log.h" | 13 #include "vm/log.h" |
| 14 #include "vm/object.h" | 14 #include "vm/object.h" |
| 15 #include "vm/object_store.h" | 15 #include "vm/object_store.h" |
| 16 #include "vm/parser.h" | 16 #include "vm/parser.h" |
| 17 #include "vm/safepoint.h" | 17 #include "vm/safepoint.h" |
| 18 #include "vm/service_event.h" | 18 #include "vm/service_event.h" |
| 19 #include "vm/stack_frame.h" | 19 #include "vm/stack_frame.h" |
| 20 #include "vm/thread.h" | 20 #include "vm/thread.h" |
| 21 #include "vm/timeline.h" | 21 #include "vm/timeline.h" |
| 22 #include "vm/visitor.h" | 22 #include "vm/visitor.h" |
| 23 | 23 |
| 24 namespace dart { | 24 namespace dart { |
| 25 | 25 |
| 26 DEFINE_FLAG(bool, trace_reload, false, "Trace isolate reloading"); | 26 DEFINE_FLAG(bool, trace_reload, false, "Trace isolate reloading"); |
| 27 DEFINE_FLAG(bool, trace_reload_verbose, false, |
| 28 "trace isolate reloading verbose"); |
| 27 DEFINE_FLAG(bool, identity_reload, false, "Enable checks for identity reload."); | 29 DEFINE_FLAG(bool, identity_reload, false, "Enable checks for identity reload."); |
| 28 DEFINE_FLAG(int, reload_every, 0, "Reload every N stack overflow checks."); | 30 DEFINE_FLAG(int, reload_every, 0, "Reload every N stack overflow checks."); |
| 29 DEFINE_FLAG(bool, reload_every_optimized, true, "Only from optimized code."); | 31 DEFINE_FLAG(bool, reload_every_optimized, true, "Only from optimized code."); |
| 30 DEFINE_FLAG(bool, reload_every_back_off, false, | 32 DEFINE_FLAG(bool, reload_every_back_off, false, |
| 31 "Double the --reload-every value after each reload."); | 33 "Double the --reload-every value after each reload."); |
| 32 DEFINE_FLAG(bool, check_reloaded, false, | 34 DEFINE_FLAG(bool, check_reloaded, false, |
| 33 "Assert that an isolate has reloaded at least once.") | 35 "Assert that an isolate has reloaded at least once.") |
| 34 #ifndef PRODUCT | 36 #ifndef PRODUCT |
| 35 | 37 |
| 36 #define I (isolate()) | 38 #define I (isolate()) |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 110 static uword Hash(const Object& obj) { | 112 static uword Hash(const Object& obj) { |
| 111 if (obj.IsLibrary()) { | 113 if (obj.IsLibrary()) { |
| 112 return Library::Cast(obj).UrlHash(); | 114 return Library::Cast(obj).UrlHash(); |
| 113 } else if (obj.IsClass()) { | 115 } else if (obj.IsClass()) { |
| 114 if (Class::Cast(obj).id() == kFreeListElement) { | 116 if (Class::Cast(obj).id() == kFreeListElement) { |
| 115 return 0; | 117 return 0; |
| 116 } | 118 } |
| 117 return String::HashRawSymbol(Class::Cast(obj).Name()); | 119 return String::HashRawSymbol(Class::Cast(obj).Name()); |
| 118 } else if (obj.IsField()) { | 120 } else if (obj.IsField()) { |
| 119 return String::HashRawSymbol(Field::Cast(obj).name()); | 121 return String::HashRawSymbol(Field::Cast(obj).name()); |
| 122 } else if (obj.IsInstance()) { |
| 123 return Smi::Handle(Smi::RawCast(Instance::Cast(obj).HashCode())).Value(); |
| 120 } | 124 } |
| 121 return 0; | 125 return 0; |
| 122 } | 126 } |
| 123 }; | 127 }; |
| 124 | 128 |
| 125 | 129 |
| 126 bool IsolateReloadContext::IsSameField(const Field& a, const Field& b) { | 130 bool IsolateReloadContext::IsSameField(const Field& a, const Field& b) { |
| 127 if (a.is_static() != b.is_static()) { | 131 if (a.is_static() != b.is_static()) { |
| 128 return false; | 132 return false; |
| 129 } | 133 } |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 181 saved_num_cids_(-1), | 185 saved_num_cids_(-1), |
| 182 saved_class_table_(NULL), | 186 saved_class_table_(NULL), |
| 183 num_saved_libs_(-1), | 187 num_saved_libs_(-1), |
| 184 script_uri_(String::null()), | 188 script_uri_(String::null()), |
| 185 error_(Error::null()), | 189 error_(Error::null()), |
| 186 old_classes_set_storage_(Array::null()), | 190 old_classes_set_storage_(Array::null()), |
| 187 class_map_storage_(Array::null()), | 191 class_map_storage_(Array::null()), |
| 188 old_libraries_set_storage_(Array::null()), | 192 old_libraries_set_storage_(Array::null()), |
| 189 library_map_storage_(Array::null()), | 193 library_map_storage_(Array::null()), |
| 190 become_map_storage_(Array::null()), | 194 become_map_storage_(Array::null()), |
| 195 become_enum_mappings_(GrowableObjectArray::null()), |
| 191 saved_root_library_(Library::null()), | 196 saved_root_library_(Library::null()), |
| 192 saved_libraries_(GrowableObjectArray::null()) { | 197 saved_libraries_(GrowableObjectArray::null()) { |
| 193 // NOTE: DO NOT ALLOCATE ANY RAW OBJECTS HERE. The IsolateReloadContext is not | 198 // NOTE: DO NOT ALLOCATE ANY RAW OBJECTS HERE. The IsolateReloadContext is not |
| 194 // associated with the isolate yet and if a GC is triggered here the raw | 199 // associated with the isolate yet and if a GC is triggered here the raw |
| 195 // objects will not be properly accounted for. | 200 // objects will not be properly accounted for. |
| 196 } | 201 } |
| 197 | 202 |
| 198 | 203 |
| 199 IsolateReloadContext::~IsolateReloadContext() { | 204 IsolateReloadContext::~IsolateReloadContext() { |
| 200 } | 205 } |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 237 old_classes_set_storage_ = | 242 old_classes_set_storage_ = |
| 238 HashTables::New<UnorderedHashSet<ClassMapTraits> >(4); | 243 HashTables::New<UnorderedHashSet<ClassMapTraits> >(4); |
| 239 class_map_storage_ = | 244 class_map_storage_ = |
| 240 HashTables::New<UnorderedHashMap<ClassMapTraits> >(4); | 245 HashTables::New<UnorderedHashMap<ClassMapTraits> >(4); |
| 241 old_libraries_set_storage_ = | 246 old_libraries_set_storage_ = |
| 242 HashTables::New<UnorderedHashSet<LibraryMapTraits> >(4); | 247 HashTables::New<UnorderedHashSet<LibraryMapTraits> >(4); |
| 243 library_map_storage_ = | 248 library_map_storage_ = |
| 244 HashTables::New<UnorderedHashMap<LibraryMapTraits> >(4); | 249 HashTables::New<UnorderedHashMap<LibraryMapTraits> >(4); |
| 245 become_map_storage_ = | 250 become_map_storage_ = |
| 246 HashTables::New<UnorderedHashMap<BecomeMapTraits> >(4); | 251 HashTables::New<UnorderedHashMap<BecomeMapTraits> >(4); |
| 252 // Keep a separate array for enum mappings to avoid having to invoke |
| 253 // hashCode on the instances. |
| 254 become_enum_mappings_ = GrowableObjectArray::New(Heap::kOld); |
| 247 | 255 |
| 248 // Disable the background compiler while we are performing the reload. | 256 // Disable the background compiler while we are performing the reload. |
| 249 BackgroundCompiler::Disable(); | 257 BackgroundCompiler::Disable(); |
| 250 | 258 |
| 251 if (FLAG_write_protect_code) { | 259 if (FLAG_write_protect_code) { |
| 252 // Disable code page write protection while we are reloading. | 260 // Disable code page write protection while we are reloading. |
| 253 I->heap()->WriteProtectCode(false); | 261 I->heap()->WriteProtectCode(false); |
| 254 } | 262 } |
| 255 | 263 |
| 256 // Ensure all functions on the stack have unoptimized code. | 264 // Ensure all functions on the stack have unoptimized code. |
| (...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 595 { | 603 { |
| 596 UnorderedHashMap<ClassMapTraits>::Iterator it(&class_map); | 604 UnorderedHashMap<ClassMapTraits>::Iterator it(&class_map); |
| 597 while (it.MoveNext()) { | 605 while (it.MoveNext()) { |
| 598 const intptr_t entry = it.Current(); | 606 const intptr_t entry = it.Current(); |
| 599 new_cls = Class::RawCast(class_map.GetKey(entry)); | 607 new_cls = Class::RawCast(class_map.GetKey(entry)); |
| 600 cls = Class::RawCast(class_map.GetPayload(entry, 0)); | 608 cls = Class::RawCast(class_map.GetPayload(entry, 0)); |
| 601 if (new_cls.raw() != cls.raw()) { | 609 if (new_cls.raw() != cls.raw()) { |
| 602 ASSERT(new_cls.is_enum_class() == cls.is_enum_class()); | 610 ASSERT(new_cls.is_enum_class() == cls.is_enum_class()); |
| 603 if (new_cls.is_enum_class() && new_cls.is_finalized()) { | 611 if (new_cls.is_enum_class() && new_cls.is_finalized()) { |
| 604 new_cls.ReplaceEnum(cls); | 612 new_cls.ReplaceEnum(cls); |
| 613 } else { |
| 614 new_cls.CopyStaticFieldValues(cls); |
| 605 } | 615 } |
| 606 new_cls.CopyStaticFieldValues(cls); | |
| 607 cls.PatchFieldsAndFunctions(); | 616 cls.PatchFieldsAndFunctions(); |
| 608 } | 617 } |
| 609 } | 618 } |
| 610 } | 619 } |
| 611 | 620 |
| 612 class_map.Release(); | 621 class_map.Release(); |
| 613 } | 622 } |
| 614 | 623 |
| 615 // Copy over certain properties of libraries, e.g. is the library | 624 // Copy over certain properties of libraries, e.g. is the library |
| 616 // debuggable? | 625 // debuggable? |
| (...skipping 22 matching lines...) Expand all Loading... |
| 639 } | 648 } |
| 640 | 649 |
| 641 { | 650 { |
| 642 TIMELINE_SCOPE(UpdateLibrariesArray); | 651 TIMELINE_SCOPE(UpdateLibrariesArray); |
| 643 // Update the libraries array. | 652 // Update the libraries array. |
| 644 Library& lib = Library::Handle(); | 653 Library& lib = Library::Handle(); |
| 645 const GrowableObjectArray& libs = GrowableObjectArray::Handle( | 654 const GrowableObjectArray& libs = GrowableObjectArray::Handle( |
| 646 I->object_store()->libraries()); | 655 I->object_store()->libraries()); |
| 647 for (intptr_t i = 0; i < libs.Length(); i++) { | 656 for (intptr_t i = 0; i < libs.Length(); i++) { |
| 648 lib = Library::RawCast(libs.At(i)); | 657 lib = Library::RawCast(libs.At(i)); |
| 649 TIR_Print("Lib '%s' at index %" Pd "\n", lib.ToCString(), i); | 658 VTIR_Print("Lib '%s' at index %" Pd "\n", lib.ToCString(), i); |
| 650 lib.set_index(i); | 659 lib.set_index(i); |
| 651 } | 660 } |
| 652 | 661 |
| 653 // Initialize library side table. | 662 // Initialize library side table. |
| 654 library_infos_.SetLength(libs.Length()); | 663 library_infos_.SetLength(libs.Length()); |
| 655 for (intptr_t i = 0; i < libs.Length(); i++) { | 664 for (intptr_t i = 0; i < libs.Length(); i++) { |
| 656 lib = Library::RawCast(libs.At(i)); | 665 lib = Library::RawCast(libs.At(i)); |
| 657 // Mark the library dirty if it comes after the libraries we saved. | 666 // Mark the library dirty if it comes after the libraries we saved. |
| 658 library_infos_[i].dirty = i >= num_saved_libs_; | 667 library_infos_[i].dirty = i >= num_saved_libs_; |
| 659 } | 668 } |
| 660 } | 669 } |
| 661 | 670 |
| 662 { | 671 { |
| 672 const GrowableObjectArray& become_enum_mappings = |
| 673 GrowableObjectArray::Handle(become_enum_mappings_); |
| 663 UnorderedHashMap<BecomeMapTraits> become_map(become_map_storage_); | 674 UnorderedHashMap<BecomeMapTraits> become_map(become_map_storage_); |
| 664 intptr_t replacement_count = become_map.NumOccupied(); | 675 intptr_t replacement_count = become_map.NumOccupied() + |
| 676 become_enum_mappings.Length() / 2; |
| 665 const Array& before = | 677 const Array& before = |
| 666 Array::Handle(Array::New(replacement_count, Heap::kOld)); | 678 Array::Handle(Array::New(replacement_count, Heap::kOld)); |
| 667 const Array& after = | 679 const Array& after = |
| 668 Array::Handle(Array::New(replacement_count, Heap::kOld)); | 680 Array::Handle(Array::New(replacement_count, Heap::kOld)); |
| 669 Object& obj = Object::Handle(); | 681 Object& obj = Object::Handle(); |
| 670 intptr_t replacement_index = 0; | 682 intptr_t replacement_index = 0; |
| 671 UnorderedHashMap<BecomeMapTraits>::Iterator it(&become_map); | 683 UnorderedHashMap<BecomeMapTraits>::Iterator it(&become_map); |
| 672 while (it.MoveNext()) { | 684 while (it.MoveNext()) { |
| 673 const intptr_t entry = it.Current(); | 685 const intptr_t entry = it.Current(); |
| 674 obj = become_map.GetKey(entry); | 686 obj = become_map.GetKey(entry); |
| 675 before.SetAt(replacement_index, obj); | 687 before.SetAt(replacement_index, obj); |
| 676 obj = become_map.GetPayload(entry, 0); | 688 obj = become_map.GetPayload(entry, 0); |
| 677 after.SetAt(replacement_index, obj); | 689 after.SetAt(replacement_index, obj); |
| 678 replacement_index++; | 690 replacement_index++; |
| 679 } | 691 } |
| 692 for (intptr_t i = 0; i < become_enum_mappings.Length(); i += 2) { |
| 693 obj = become_enum_mappings.At(i); |
| 694 before.SetAt(replacement_index, obj); |
| 695 obj = become_enum_mappings.At(i + 1); |
| 696 after.SetAt(replacement_index, obj); |
| 697 replacement_index++; |
| 698 } |
| 680 ASSERT(replacement_index == replacement_count); | 699 ASSERT(replacement_index == replacement_count); |
| 681 become_map.Release(); | 700 become_map.Release(); |
| 682 | 701 |
| 683 Become::ElementsForwardIdentity(before, after); | 702 Become::ElementsForwardIdentity(before, after); |
| 684 } | 703 } |
| 685 | 704 |
| 686 if (FLAG_identity_reload) { | 705 if (FLAG_identity_reload) { |
| 687 if (saved_num_cids_ != I->class_table()->NumCids()) { | 706 if (saved_num_cids_ != I->class_table()->NumCids()) { |
| 688 TIR_Print("Identity reload failed! B#C=%" Pd " A#C=%" Pd "\n", | 707 TIR_Print("Identity reload failed! B#C=%" Pd " A#C=%" Pd "\n", |
| 689 saved_num_cids_, | 708 saved_num_cids_, |
| (...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1062 void IsolateReloadContext::AddBecomeMapping(const Object& old, | 1081 void IsolateReloadContext::AddBecomeMapping(const Object& old, |
| 1063 const Object& neu) { | 1082 const Object& neu) { |
| 1064 ASSERT(become_map_storage_ != Array::null()); | 1083 ASSERT(become_map_storage_ != Array::null()); |
| 1065 UnorderedHashMap<BecomeMapTraits> become_map(become_map_storage_); | 1084 UnorderedHashMap<BecomeMapTraits> become_map(become_map_storage_); |
| 1066 bool update = become_map.UpdateOrInsert(old, neu); | 1085 bool update = become_map.UpdateOrInsert(old, neu); |
| 1067 ASSERT(!update); | 1086 ASSERT(!update); |
| 1068 become_map_storage_ = become_map.Release().raw(); | 1087 become_map_storage_ = become_map.Release().raw(); |
| 1069 } | 1088 } |
| 1070 | 1089 |
| 1071 | 1090 |
| 1091 void IsolateReloadContext::AddEnumBecomeMapping(const Object& old, |
| 1092 const Object& neu) { |
| 1093 const GrowableObjectArray& become_enum_mappings = |
| 1094 GrowableObjectArray::Handle(become_enum_mappings_); |
| 1095 become_enum_mappings.Add(old); |
| 1096 become_enum_mappings.Add(neu); |
| 1097 ASSERT((become_enum_mappings.Length() % 2) == 0); |
| 1098 } |
| 1099 |
| 1100 |
| 1072 void IsolateReloadContext::RebuildDirectSubclasses() { | 1101 void IsolateReloadContext::RebuildDirectSubclasses() { |
| 1073 ClassTable* class_table = I->class_table(); | 1102 ClassTable* class_table = I->class_table(); |
| 1074 intptr_t num_cids = class_table->NumCids(); | 1103 intptr_t num_cids = class_table->NumCids(); |
| 1075 | 1104 |
| 1076 // Clear the direct subclasses for all classes. | 1105 // Clear the direct subclasses for all classes. |
| 1077 Class& cls = Class::Handle(); | 1106 Class& cls = Class::Handle(); |
| 1078 GrowableObjectArray& subclasses = GrowableObjectArray::Handle(); | 1107 GrowableObjectArray& subclasses = GrowableObjectArray::Handle(); |
| 1079 for (intptr_t i = 1; i < num_cids; i++) { | 1108 for (intptr_t i = 1; i < num_cids; i++) { |
| 1080 if (class_table->HasValidClassAt(i)) { | 1109 if (class_table->HasValidClassAt(i)) { |
| 1081 cls = class_table->At(i); | 1110 cls = class_table->At(i); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1098 ASSERT(!super_cls.IsNull()); | 1127 ASSERT(!super_cls.IsNull()); |
| 1099 super_cls.AddDirectSubclass(cls); | 1128 super_cls.AddDirectSubclass(cls); |
| 1100 } | 1129 } |
| 1101 } | 1130 } |
| 1102 } | 1131 } |
| 1103 } | 1132 } |
| 1104 | 1133 |
| 1105 #endif // !PRODUCT | 1134 #endif // !PRODUCT |
| 1106 | 1135 |
| 1107 } // namespace dart | 1136 } // namespace dart |
| OLD | NEW |