Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(544)

Side by Side Diff: runtime/vm/isolate_reload.cc

Issue 2186423002: Only reload libraries when they may have been modified. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Fixed bug with prefixed imports Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/bit_vector.h"
8 #include "vm/code_generator.h" 9 #include "vm/code_generator.h"
9 #include "vm/compiler.h" 10 #include "vm/compiler.h"
10 #include "vm/dart_api_impl.h" 11 #include "vm/dart_api_impl.h"
11 #include "vm/hash_table.h" 12 #include "vm/hash_table.h"
12 #include "vm/isolate.h" 13 #include "vm/isolate.h"
13 #include "vm/log.h" 14 #include "vm/log.h"
14 #include "vm/object.h" 15 #include "vm/object.h"
15 #include "vm/object_store.h" 16 #include "vm/object_store.h"
16 #include "vm/parser.h" 17 #include "vm/parser.h"
17 #include "vm/safepoint.h" 18 #include "vm/safepoint.h"
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 const String& a_lib_url = 173 const String& a_lib_url =
173 String::Handle(a_lib.IsNull() ? String::null() : a_lib.url()); 174 String::Handle(a_lib.IsNull() ? String::null() : a_lib.url());
174 const String& b_lib_url = 175 const String& b_lib_url =
175 String::Handle(b_lib.IsNull() ? String::null() : b_lib.url()); 176 String::Handle(b_lib.IsNull() ? String::null() : b_lib.url());
176 return a_lib_url.Equals(b_lib_url); 177 return a_lib_url.Equals(b_lib_url);
177 } 178 }
178 179
179 180
180 IsolateReloadContext::IsolateReloadContext(Isolate* isolate) 181 IsolateReloadContext::IsolateReloadContext(Isolate* isolate)
181 : start_time_micros_(OS::GetCurrentMonotonicMicros()), 182 : start_time_micros_(OS::GetCurrentMonotonicMicros()),
183 reload_timestamp_(OS::GetCurrentTimeMillis()),
Cutch 2016/07/29 14:37:04 Why does the reload context and the isolate have a
turnidge 2016/07/29 17:37:37 The isolate's reload timestamp is the timestamp of
182 isolate_(isolate), 184 isolate_(isolate),
185 reload_skipped_(false),
183 has_error_(false), 186 has_error_(false),
184 saved_num_cids_(-1), 187 saved_num_cids_(-1),
185 saved_class_table_(NULL), 188 saved_class_table_(NULL),
186 num_saved_libs_(-1), 189 num_saved_libs_(-1),
190 modified_libs_(NULL),
187 script_uri_(String::null()), 191 script_uri_(String::null()),
188 error_(Error::null()), 192 error_(Error::null()),
189 old_classes_set_storage_(Array::null()), 193 old_classes_set_storage_(Array::null()),
190 class_map_storage_(Array::null()), 194 class_map_storage_(Array::null()),
191 old_libraries_set_storage_(Array::null()), 195 old_libraries_set_storage_(Array::null()),
192 library_map_storage_(Array::null()), 196 library_map_storage_(Array::null()),
193 become_map_storage_(Array::null()), 197 become_map_storage_(Array::null()),
194 become_enum_mappings_(GrowableObjectArray::null()), 198 become_enum_mappings_(GrowableObjectArray::null()),
195 saved_root_library_(Library::null()), 199 saved_root_library_(Library::null()),
196 saved_libraries_(GrowableObjectArray::null()) { 200 saved_libraries_(GrowableObjectArray::null()) {
(...skipping 23 matching lines...) Expand all
220 ReportError(LanguageError::Handle(LanguageError::New(error_msg))); 224 ReportError(LanguageError::Handle(LanguageError::New(error_msg)));
221 } 225 }
222 226
223 227
224 void IsolateReloadContext::ReportSuccess() { 228 void IsolateReloadContext::ReportSuccess() {
225 ServiceEvent service_event(I, ServiceEvent::kIsolateReload); 229 ServiceEvent service_event(I, ServiceEvent::kIsolateReload);
226 Service::HandleEvent(&service_event); 230 Service::HandleEvent(&service_event);
227 } 231 }
228 232
229 233
230 void IsolateReloadContext::StartReload() { 234 void IsolateReloadContext::StartReload(bool force_reload) {
231 TIMELINE_SCOPE(Reload); 235 TIMELINE_SCOPE(Reload);
232 Thread* thread = Thread::Current(); 236 Thread* thread = Thread::Current();
233 ASSERT(isolate() == thread->isolate()); 237 ASSERT(isolate() == thread->isolate());
234 238
235 // Grab root library before calling CheckpointBeforeReload. 239 // Grab root library before calling CheckpointBeforeReload.
236 const Library& root_lib = Library::Handle(object_store()->root_library()); 240 const Library& root_lib = Library::Handle(object_store()->root_library());
237 ASSERT(!root_lib.IsNull()); 241 ASSERT(!root_lib.IsNull());
238 const String& root_lib_url = String::Handle(root_lib.url()); 242 const String& root_lib_url = String::Handle(root_lib.url());
239 243
244 // Check to see which libraries have been modified.
245 modified_libs_ = FindModifiedLibraries(force_reload);
246 if (!modified_libs_->Contains(root_lib.index())) {
247 ASSERT(modified_libs_->IsEmpty());
248 reload_skipped_ = true;
249 TIR_Print("Skipping reload. No libraries were modified\n");
250 return;
251 }
252
240 // Preallocate storage for maps. 253 // Preallocate storage for maps.
241 old_classes_set_storage_ = 254 old_classes_set_storage_ =
242 HashTables::New<UnorderedHashSet<ClassMapTraits> >(4); 255 HashTables::New<UnorderedHashSet<ClassMapTraits> >(4);
243 class_map_storage_ = 256 class_map_storage_ =
244 HashTables::New<UnorderedHashMap<ClassMapTraits> >(4); 257 HashTables::New<UnorderedHashMap<ClassMapTraits> >(4);
245 old_libraries_set_storage_ = 258 old_libraries_set_storage_ =
246 HashTables::New<UnorderedHashSet<LibraryMapTraits> >(4); 259 HashTables::New<UnorderedHashSet<LibraryMapTraits> >(4);
247 library_map_storage_ = 260 library_map_storage_ =
248 HashTables::New<UnorderedHashMap<LibraryMapTraits> >(4); 261 HashTables::New<UnorderedHashMap<LibraryMapTraits> >(4);
249 become_map_storage_ = 262 become_map_storage_ =
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 if (!old_cls.is_enum_class()) { 319 if (!old_cls.is_enum_class()) {
307 new_cls.CopyCanonicalConstants(old_cls); 320 new_cls.CopyCanonicalConstants(old_cls);
308 } 321 }
309 new_cls.CopyCanonicalType(old_cls); 322 new_cls.CopyCanonicalType(old_cls);
310 AddBecomeMapping(old_cls, new_cls); 323 AddBecomeMapping(old_cls, new_cls);
311 AddClassMapping(new_cls, old_cls); 324 AddClassMapping(new_cls, old_cls);
312 } 325 }
313 326
314 327
315 void IsolateReloadContext::FinishReload() { 328 void IsolateReloadContext::FinishReload() {
329 if (reload_skipped_) {
330 return;
331 }
316 BuildLibraryMapping(); 332 BuildLibraryMapping();
317 TIR_Print("---- DONE FINALIZING\n"); 333 TIR_Print("---- DONE FINALIZING\n");
318 if (ValidateReload()) { 334 if (ValidateReload()) {
319 Commit(); 335 Commit();
320 PostCommit(); 336 PostCommit();
321 } else { 337 } else {
322 Rollback(); 338 Rollback();
323 } 339 }
324 // ValidateReload mutates the direct subclass information and does 340 // ValidateReload mutates the direct subclass information and does
325 // not remove dead subclasses. Rebuild the direct subclass 341 // not remove dead subclasses. Rebuild the direct subclass
326 // information from scratch. 342 // information from scratch.
327 RebuildDirectSubclasses(); 343 RebuildDirectSubclasses();
328 344
329 if (FLAG_write_protect_code) { 345 if (FLAG_write_protect_code) {
330 // Disable code page write protection while we are reloading. 346 // Re-enable code page write protection.
331 I->heap()->WriteProtectCode(true); 347 I->heap()->WriteProtectCode(true);
332 } 348 }
333 349
334 BackgroundCompiler::Enable(); 350 BackgroundCompiler::Enable();
335 } 351 }
336 352
337 353
338 void IsolateReloadContext::AbortReload(const Error& error) { 354 void IsolateReloadContext::AbortReload(const Error& error) {
339 ReportError(error); 355 ReportError(error);
340 Rollback(); 356 Rollback();
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
427 local_saved_class_table[i] = NULL; 443 local_saved_class_table[i] = NULL;
428 } 444 }
429 } 445 }
430 old_classes_set_storage_ = old_classes_set.Release().raw(); 446 old_classes_set_storage_ = old_classes_set.Release().raw();
431 // Assigning the field must be done after saving the class table. 447 // Assigning the field must be done after saving the class table.
432 saved_class_table_ = local_saved_class_table; 448 saved_class_table_ = local_saved_class_table;
433 TIR_Print("---- System had %" Pd " classes\n", saved_num_cids_); 449 TIR_Print("---- System had %" Pd " classes\n", saved_num_cids_);
434 } 450 }
435 451
436 452
437 bool IsolateReloadContext::IsCleanLibrary(const Library& lib) { 453 Dart_FileModifiedCallback IsolateReloadContext::file_modified_callback_ = NULL;
438 return lib.is_dart_scheme(); 454
455
456 bool IsolateReloadContext::ScriptModifiedSince(const Script& script,
457 int64_t since) {
458 if (file_modified_callback_ == NULL) {
459 return true;
460 }
461 // We use the resolved url to determine if the script has been modified.
462 const String& url = String::Handle(script.resolved_url());
463 const char* url_chars = url.ToCString();
464 return (*file_modified_callback_)(url_chars, since);
439 } 465 }
440 466
441 467
468 static void PropagateLibraryModified(
469 const ZoneGrowableArray<ZoneGrowableArray<intptr_t>* >* imported_by,
470 intptr_t lib_index,
471 BitVector* modified_libs) {
472 ZoneGrowableArray<intptr_t>* dep_libs = (*imported_by)[lib_index];
473 for (intptr_t i = 0; i < dep_libs->length(); i++) {
474 intptr_t dep_lib_index = (*dep_libs)[i];
475 if (!modified_libs->Contains(dep_lib_index)) {
476 modified_libs->Add(dep_lib_index);
477 PropagateLibraryModified(imported_by, dep_lib_index, modified_libs);
478 }
479 }
480 }
481
482
483 BitVector* IsolateReloadContext::FindModifiedLibraries(bool force_reload) {
484 Thread* thread = Thread::Current();
485 int64_t last_reload = I->reload_timestamp();
486
487 const GrowableObjectArray& libs =
488 GrowableObjectArray::Handle(object_store()->libraries());
489 Library& lib = Library::Handle();
490 Array& scripts = Array::Handle();
491 Script& script = Script::Handle();
492 intptr_t num_libs = libs.Length();
493
494 // Construct the imported-by graph.
495 ZoneGrowableArray<ZoneGrowableArray<intptr_t>* >* imported_by =
496 new ZoneGrowableArray<ZoneGrowableArray<intptr_t>* >(num_libs);
497 imported_by->SetLength(num_libs);
498 for (intptr_t i = 0; i < num_libs; i++) {
499 (*imported_by)[i] = new ZoneGrowableArray<intptr_t>();
500 }
501 Array& imports = Array::Handle();
502 Namespace& ns = Namespace::Handle();
503 Library& target = Library::Handle();
504
505 for (intptr_t lib_idx = 0; lib_idx < num_libs; lib_idx++) {
506 lib ^= libs.At(lib_idx);
507 ASSERT(lib_idx == lib.index());
508 if (lib.is_dart_scheme()) {
509 // We don't care about imports among dart scheme libraries.
510 continue;
511 }
512
513 // Add imports to the import-by graph.
514 imports = lib.imports();
515 for (intptr_t import_idx = 0; import_idx < imports.Length(); import_idx++) {
516 ns ^= imports.At(import_idx);
517 if (!ns.IsNull()) {
518 target = ns.library();
519 (*imported_by)[target.index()]->Add(lib.index());
520 }
521 }
522
523 // Add prefixed imports to the import-by graph.
524 DictionaryIterator entries(lib);
525 Object& entry = Object::Handle();
526 LibraryPrefix& prefix = LibraryPrefix::Handle();
527 while (entries.HasNext()) {
528 entry = entries.GetNext();
529 if (entry.IsLibraryPrefix()) {
530 prefix ^= entry.raw();
531 imports = prefix.imports();
532 for (intptr_t import_idx = 0; import_idx < imports.Length();
533 import_idx++) {
534 ns ^= imports.At(import_idx);
535 if (!ns.IsNull()) {
536 target = ns.library();
537 (*imported_by)[target.index()]->Add(lib.index());
538 }
539 }
540 }
541 }
542 }
543
544 BitVector* modified_libs = new(Z) BitVector(Z, num_libs);
545
546 for (intptr_t lib_idx = 0; lib_idx < num_libs; lib_idx++) {
547 lib ^= libs.At(lib_idx);
548 if (lib.is_dart_scheme() || modified_libs->Contains(lib_idx)) {
549 // We don't consider dart scheme libraries during reload. If
550 // the modified libs set already contains this library, then we
551 // have already visited it.
552 continue;
553 }
554 scripts = lib.LoadedScripts();
555 for (intptr_t script_idx = 0; script_idx < scripts.Length(); script_idx++) {
556 script ^= scripts.At(script_idx);
557 if (force_reload) {
558 modified_libs->Add(lib_idx);
559 break;
560 }
561 if (ScriptModifiedSince(script, last_reload)) {
Cutch 2016/07/29 14:37:04 maybe merge these two ifs: if (force_reload || Sc
turnidge 2016/07/29 17:37:37 Done.
562 modified_libs->Add(lib_idx);
563 break;
564 }
565 }
566 if (modified_libs->Contains(lib_idx)) {
567 PropagateLibraryModified(imported_by, lib_idx, modified_libs);
Cutch 2016/07/29 14:37:04 Could this be rolled into the if statement above?
turnidge 2016/07/29 17:37:37 Done.
568 }
569 }
570
571 return modified_libs;
572 }
573
574
442 void IsolateReloadContext::CheckpointLibraries() { 575 void IsolateReloadContext::CheckpointLibraries() {
443 TIMELINE_SCOPE(CheckpointLibraries); 576 TIMELINE_SCOPE(CheckpointLibraries);
444 577
445 // Save the root library in case we abort the reload. 578 // Save the root library in case we abort the reload.
446 const Library& root_lib = 579 const Library& root_lib =
447 Library::Handle(object_store()->root_library()); 580 Library::Handle(object_store()->root_library());
448 set_saved_root_library(root_lib); 581 set_saved_root_library(root_lib);
449 582
450 // Save the old libraries array in case we abort the reload. 583 // Save the old libraries array in case we abort the reload.
451 const GrowableObjectArray& libs = 584 const GrowableObjectArray& libs =
452 GrowableObjectArray::Handle(object_store()->libraries()); 585 GrowableObjectArray::Handle(object_store()->libraries());
453 set_saved_libraries(libs); 586 set_saved_libraries(libs);
454 587
455 // Make a filtered copy of the old libraries array. Keep "clean" libraries 588 // Make a filtered copy of the old libraries array. Keep "clean" libraries
456 // that we will use instead of reloading. 589 // that we will use instead of reloading.
457 const GrowableObjectArray& new_libs = GrowableObjectArray::Handle( 590 const GrowableObjectArray& new_libs = GrowableObjectArray::Handle(
458 GrowableObjectArray::New(Heap::kOld)); 591 GrowableObjectArray::New(Heap::kOld));
459 Library& lib = Library::Handle(); 592 Library& lib = Library::Handle();
460 UnorderedHashSet<LibraryMapTraits> 593 UnorderedHashSet<LibraryMapTraits>
461 old_libraries_set(old_libraries_set_storage_); 594 old_libraries_set(old_libraries_set_storage_);
462 num_saved_libs_ = 0; 595 num_saved_libs_ = 0;
463 for (intptr_t i = 0; i < libs.Length(); i++) { 596 for (intptr_t i = 0; i < libs.Length(); i++) {
464 lib ^= libs.At(i); 597 lib ^= libs.At(i);
465 if (IsCleanLibrary(lib)) { 598 if (modified_libs_->Contains(i)) {
599 // We are going to reload this library. Clear the index.
600 lib.set_index(-1);
601 } else {
466 // We are preserving this library across the reload, assign its new index 602 // We are preserving this library across the reload, assign its new index
467 lib.set_index(new_libs.Length()); 603 lib.set_index(new_libs.Length());
468 new_libs.Add(lib, Heap::kOld); 604 new_libs.Add(lib, Heap::kOld);
469 num_saved_libs_++; 605 num_saved_libs_++;
470 } else {
471 // We are going to reload this library. Clear the index.
472 lib.set_index(-1);
473 } 606 }
474 // Add old library to old libraries set. 607 // Add old library to old libraries set.
475 bool already_present = old_libraries_set.Insert(lib); 608 bool already_present = old_libraries_set.Insert(lib);
476 ASSERT(!already_present); 609 ASSERT(!already_present);
477 } 610 }
611 modified_libs_ = NULL; // Renumbering the libraries has invalidated this.
478 old_libraries_set_storage_ = old_libraries_set.Release().raw(); 612 old_libraries_set_storage_ = old_libraries_set.Release().raw();
479 613
480 // Reset the registered libraries to the filtered array. 614 // Reset the registered libraries to the filtered array.
481 Library::RegisterLibraries(Thread::Current(), new_libs); 615 Library::RegisterLibraries(Thread::Current(), new_libs);
482 // Reset the root library to null. 616 // Reset the root library to null.
483 object_store()->set_root_library(Library::Handle()); 617 object_store()->set_root_library(Library::Handle());
484 } 618 }
485 619
486 620
487 // While reloading everything we do must be reversible so that we can abort 621 // While reloading everything we do must be reversible so that we can abort
(...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after
1019 return lib.raw(); 1153 return lib.raw();
1020 } 1154 }
1021 1155
1022 1156
1023 void IsolateReloadContext::BuildLibraryMapping() { 1157 void IsolateReloadContext::BuildLibraryMapping() {
1024 const GrowableObjectArray& libs = 1158 const GrowableObjectArray& libs =
1025 GrowableObjectArray::Handle(object_store()->libraries()); 1159 GrowableObjectArray::Handle(object_store()->libraries());
1026 1160
1027 Library& replacement_or_new = Library::Handle(); 1161 Library& replacement_or_new = Library::Handle();
1028 Library& old = Library::Handle(); 1162 Library& old = Library::Handle();
1029 for (intptr_t i = 0; i < libs.Length(); i++) { 1163 for (intptr_t i = num_saved_libs_; i < libs.Length(); i++) {
1030 replacement_or_new = Library::RawCast(libs.At(i)); 1164 replacement_or_new = Library::RawCast(libs.At(i));
1031 if (IsCleanLibrary(replacement_or_new)) {
1032 continue;
1033 }
1034 old ^= OldLibraryOrNull(replacement_or_new); 1165 old ^= OldLibraryOrNull(replacement_or_new);
1035 if (old.IsNull()) { 1166 if (old.IsNull()) {
1036 if (FLAG_identity_reload) { 1167 if (FLAG_identity_reload) {
1037 TIR_Print("Could not find original library for %s\n", 1168 TIR_Print("Could not find original library for %s\n",
1038 replacement_or_new.ToCString()); 1169 replacement_or_new.ToCString());
1039 UNREACHABLE(); 1170 UNREACHABLE();
1040 } 1171 }
1041 // New library. 1172 // New library.
1042 AddLibraryMapping(replacement_or_new, replacement_or_new); 1173 AddLibraryMapping(replacement_or_new, replacement_or_new);
1043 } else { 1174 } else {
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
1131 ASSERT(!super_cls.IsNull()); 1262 ASSERT(!super_cls.IsNull());
1132 super_cls.AddDirectSubclass(cls); 1263 super_cls.AddDirectSubclass(cls);
1133 } 1264 }
1134 } 1265 }
1135 } 1266 }
1136 } 1267 }
1137 1268
1138 #endif // !PRODUCT 1269 #endif // !PRODUCT
1139 1270
1140 } // namespace dart 1271 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698