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

Unified 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: Code review Created 4 years, 5 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/isolate_reload.h ('k') | runtime/vm/isolate_reload_test.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/isolate_reload.cc
diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc
index 75102c9d1f089b71142cf02708a03df53f6d9a95..f464e34da0217dabf35628f0b9077b21c1f99622 100644
--- a/runtime/vm/isolate_reload.cc
+++ b/runtime/vm/isolate_reload.cc
@@ -5,6 +5,7 @@
#include "vm/isolate_reload.h"
#include "vm/become.h"
+#include "vm/bit_vector.h"
#include "vm/code_generator.h"
#include "vm/compiler.h"
#include "vm/dart_api_impl.h"
@@ -179,11 +180,14 @@ bool IsolateReloadContext::IsSameLibrary(
IsolateReloadContext::IsolateReloadContext(Isolate* isolate)
: start_time_micros_(OS::GetCurrentMonotonicMicros()),
+ reload_timestamp_(OS::GetCurrentTimeMillis()),
isolate_(isolate),
+ reload_skipped_(false),
has_error_(false),
saved_num_cids_(-1),
saved_class_table_(NULL),
num_saved_libs_(-1),
+ modified_libs_(NULL),
script_uri_(String::null()),
error_(Error::null()),
old_classes_set_storage_(Array::null()),
@@ -227,7 +231,7 @@ void IsolateReloadContext::ReportSuccess() {
}
-void IsolateReloadContext::StartReload() {
+void IsolateReloadContext::StartReload(bool force_reload) {
TIMELINE_SCOPE(Reload);
Thread* thread = Thread::Current();
ASSERT(isolate() == thread->isolate());
@@ -237,6 +241,15 @@ void IsolateReloadContext::StartReload() {
ASSERT(!root_lib.IsNull());
const String& root_lib_url = String::Handle(root_lib.url());
+ // Check to see which libraries have been modified.
+ modified_libs_ = FindModifiedLibraries(force_reload);
+ if (!modified_libs_->Contains(root_lib.index())) {
+ ASSERT(modified_libs_->IsEmpty());
+ reload_skipped_ = true;
+ TIR_Print("Skipping reload. No libraries were modified\n");
+ return;
+ }
+
// Preallocate storage for maps.
old_classes_set_storage_ =
HashTables::New<UnorderedHashSet<ClassMapTraits> >(4);
@@ -313,11 +326,15 @@ void IsolateReloadContext::RegisterClass(const Class& new_cls) {
void IsolateReloadContext::FinishReload() {
+ if (reload_skipped_) {
+ return;
+ }
BuildLibraryMapping();
TIR_Print("---- DONE FINALIZING\n");
if (ValidateReload()) {
Commit();
PostCommit();
+ isolate()->set_last_reload_timestamp(reload_timestamp_);
} else {
Rollback();
}
@@ -327,7 +344,7 @@ void IsolateReloadContext::FinishReload() {
RebuildDirectSubclasses();
if (FLAG_write_protect_code) {
- // Disable code page write protection while we are reloading.
+ // Re-enable code page write protection.
I->heap()->WriteProtectCode(true);
}
@@ -434,8 +451,119 @@ void IsolateReloadContext::CheckpointClasses() {
}
-bool IsolateReloadContext::IsCleanLibrary(const Library& lib) {
- return lib.is_dart_scheme();
+Dart_FileModifiedCallback IsolateReloadContext::file_modified_callback_ = NULL;
+
+
+bool IsolateReloadContext::ScriptModifiedSince(const Script& script,
+ int64_t since) {
+ if (file_modified_callback_ == NULL) {
+ return true;
+ }
+ // We use the resolved url to determine if the script has been modified.
+ const String& url = String::Handle(script.resolved_url());
+ const char* url_chars = url.ToCString();
+ return (*file_modified_callback_)(url_chars, since);
+}
+
+
+static void PropagateLibraryModified(
+ const ZoneGrowableArray<ZoneGrowableArray<intptr_t>* >* imported_by,
+ intptr_t lib_index,
+ BitVector* modified_libs) {
+ ZoneGrowableArray<intptr_t>* dep_libs = (*imported_by)[lib_index];
+ for (intptr_t i = 0; i < dep_libs->length(); i++) {
+ intptr_t dep_lib_index = (*dep_libs)[i];
+ if (!modified_libs->Contains(dep_lib_index)) {
+ modified_libs->Add(dep_lib_index);
+ PropagateLibraryModified(imported_by, dep_lib_index, modified_libs);
+ }
+ }
+}
+
+
+BitVector* IsolateReloadContext::FindModifiedLibraries(bool force_reload) {
+ Thread* thread = Thread::Current();
+ int64_t last_reload = I->last_reload_timestamp();
+
+ const GrowableObjectArray& libs =
+ GrowableObjectArray::Handle(object_store()->libraries());
+ Library& lib = Library::Handle();
+ Array& scripts = Array::Handle();
+ Script& script = Script::Handle();
+ intptr_t num_libs = libs.Length();
+
+ // Construct the imported-by graph.
+ ZoneGrowableArray<ZoneGrowableArray<intptr_t>* >* imported_by =
+ new ZoneGrowableArray<ZoneGrowableArray<intptr_t>* >(num_libs);
+ imported_by->SetLength(num_libs);
+ for (intptr_t i = 0; i < num_libs; i++) {
+ (*imported_by)[i] = new ZoneGrowableArray<intptr_t>();
+ }
+ Array& imports = Array::Handle();
+ Namespace& ns = Namespace::Handle();
+ Library& target = Library::Handle();
+
+ for (intptr_t lib_idx = 0; lib_idx < num_libs; lib_idx++) {
+ lib ^= libs.At(lib_idx);
+ ASSERT(lib_idx == lib.index());
+ if (lib.is_dart_scheme()) {
+ // We don't care about imports among dart scheme libraries.
+ continue;
+ }
+
+ // Add imports to the import-by graph.
+ imports = lib.imports();
+ for (intptr_t import_idx = 0; import_idx < imports.Length(); import_idx++) {
+ ns ^= imports.At(import_idx);
+ if (!ns.IsNull()) {
+ target = ns.library();
+ (*imported_by)[target.index()]->Add(lib.index());
+ }
+ }
+
+ // Add prefixed imports to the import-by graph.
+ DictionaryIterator entries(lib);
+ Object& entry = Object::Handle();
+ LibraryPrefix& prefix = LibraryPrefix::Handle();
+ while (entries.HasNext()) {
+ entry = entries.GetNext();
+ if (entry.IsLibraryPrefix()) {
+ prefix ^= entry.raw();
+ imports = prefix.imports();
+ for (intptr_t import_idx = 0; import_idx < imports.Length();
+ import_idx++) {
+ ns ^= imports.At(import_idx);
+ if (!ns.IsNull()) {
+ target = ns.library();
+ (*imported_by)[target.index()]->Add(lib.index());
+ }
+ }
+ }
+ }
+ }
+
+ BitVector* modified_libs = new(Z) BitVector(Z, num_libs);
+
+ for (intptr_t lib_idx = 0; lib_idx < num_libs; lib_idx++) {
+ lib ^= libs.At(lib_idx);
+ if (lib.is_dart_scheme() || modified_libs->Contains(lib_idx)) {
+ // We don't consider dart scheme libraries during reload. If
+ // the modified libs set already contains this library, then we
+ // have already visited it.
+ continue;
+ }
+ scripts = lib.LoadedScripts();
+ for (intptr_t script_idx = 0; script_idx < scripts.Length(); script_idx++) {
+ script ^= scripts.At(script_idx);
+ if (force_reload || ScriptModifiedSince(script, last_reload)) {
+ modified_libs->Add(lib_idx);
+ PropagateLibraryModified(imported_by, lib_idx, modified_libs);
+ break;
+ }
+ }
+ }
+
+ return modified_libs;
}
@@ -462,19 +590,20 @@ void IsolateReloadContext::CheckpointLibraries() {
num_saved_libs_ = 0;
for (intptr_t i = 0; i < libs.Length(); i++) {
lib ^= libs.At(i);
- if (IsCleanLibrary(lib)) {
+ if (modified_libs_->Contains(i)) {
+ // We are going to reload this library. Clear the index.
+ lib.set_index(-1);
+ } else {
// We are preserving this library across the reload, assign its new index
lib.set_index(new_libs.Length());
new_libs.Add(lib, Heap::kOld);
num_saved_libs_++;
- } else {
- // We are going to reload this library. Clear the index.
- lib.set_index(-1);
}
// Add old library to old libraries set.
bool already_present = old_libraries_set.Insert(lib);
ASSERT(!already_present);
}
+ modified_libs_ = NULL; // Renumbering the libraries has invalidated this.
old_libraries_set_storage_ = old_libraries_set.Release().raw();
// Reset the registered libraries to the filtered array.
@@ -1026,11 +1155,8 @@ void IsolateReloadContext::BuildLibraryMapping() {
Library& replacement_or_new = Library::Handle();
Library& old = Library::Handle();
- for (intptr_t i = 0; i < libs.Length(); i++) {
+ for (intptr_t i = num_saved_libs_; i < libs.Length(); i++) {
replacement_or_new = Library::RawCast(libs.At(i));
- if (IsCleanLibrary(replacement_or_new)) {
- continue;
- }
old ^= OldLibraryOrNull(replacement_or_new);
if (old.IsNull()) {
if (FLAG_identity_reload) {
« no previous file with comments | « runtime/vm/isolate_reload.h ('k') | runtime/vm/isolate_reload_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698