diff --git a/common/settings.cc b/common/settings.cc index 9aa8997ba947bca6599d5ac0ad812e6abab8d5de..8123b1d321ef6c9d00de1bd4bc4d5a0ebccd6eb7 100644 --- a/common/settings.cc +++ b/common/settings.cc @@ -11,6 +11,7 @@ namespace blink { std::string Settings::ToString() const { std::stringstream stream; stream << "Settings: " << std::endl; + stream << "script_snapshot_path: " << script_snapshot_path << std::endl; stream << "vm_snapshot_data_path: " << vm_snapshot_data_path << std::endl; stream << "vm_snapshot_instr_path: " << vm_snapshot_instr_path << std::endl; stream << "isolate_snapshot_data_path: " << isolate_snapshot_data_path diff --git a/common/settings.h b/common/settings.h index 1c0002e7ad7d655493cdfe18b7bfa3098df16f54..124529b90c57d696a9833b058951f46aedfc5d9b 100644 --- a/common/settings.h +++ b/common/settings.h @@ -23,6 +23,9 @@ using TaskObserverRemove = std::function; struct Settings { // VM settings + std::string script_snapshot_path; + std::string platform_kernel_path; + std::string vm_snapshot_data_path; std::string vm_snapshot_instr_path; std::string isolate_snapshot_data_path; diff --git a/lib/snapshot/BUILD.gn b/lib/snapshot/BUILD.gn index 99e3c2f9638aa889759a8c1c295601c87e8cc96e..d257830ebd6ba289b2764f7397eb54ffc1db4ba6 100644 --- a/lib/snapshot/BUILD.gn +++ b/lib/snapshot/BUILD.gn @@ -25,145 +25,199 @@ copy("generate_dart_ui") { ] } -# Fuchsia's snapshot requires a different platform with extra dart: libraries. -if (!is_fuchsia) { - compiled_action("generate_snapshot_bin") { - tool = "//third_party/dart/runtime/bin:gen_snapshot" - - platform_kernel = "$root_out_dir/flutter_patched_sdk/platform_strong.dill" - inputs = [ - platform_kernel, - ] - deps = [ - ":kernel_platform_files", - ] - - vm_snapshot_data = "$target_gen_dir/vm_isolate_snapshot.bin" - vm_snapshot_instructions = "$target_gen_dir/vm_snapshot_instructions.bin" - isolate_snapshot_data = "$target_gen_dir/isolate_snapshot.bin" - isolate_snapshot_instructions = - "$target_gen_dir/isolate_snapshot_instructions.bin" - outputs = [ - vm_snapshot_data, - vm_snapshot_instructions, - isolate_snapshot_data, - isolate_snapshot_instructions, - ] - - args = [ - "--snapshot_kind=core", - "--await_is_keyword", - "--enable_mirrors=false", - "--vm_snapshot_data=" + rebase_path(vm_snapshot_data), - "--vm_snapshot_instructions=" + rebase_path(vm_snapshot_instructions), - "--isolate_snapshot_data=" + rebase_path(isolate_snapshot_data), - "--isolate_snapshot_instructions=" + - rebase_path(isolate_snapshot_instructions), - rebase_path(platform_kernel), - ] - - if (is_debug) { - args += [ - "--enable_asserts", - "--enable_type_checks", - "--error_on_bad_type", - "--error_on_bad_override", - ] +action("generate_snapshot_bin") { + if (is_fuchsia) { + snapshot_dart = "snapshot_fuchsia.dart" + + # TODO(rmacnak): Fuchsia cross builds use the wrong Dart target + # architecture, and have added steps that depend on this error for + # reasonable build times (e.g., invoking the analyzer). + if (target_cpu == host_cpu) { + snapshot_kind = "core-jit" + } else { + snapshot_kind = "core" } + } else { + snapshot_dart = "snapshot.dart" + snapshot_kind = "core" } - # Generates an assembly file defining a given symbol with the bytes from a - # binary file. Places the symbol in a text section if 'executable' is true, - # otherwise places the symbol in a read-only data section. - template("bin_to_assembly") { - assert(defined(invoker.deps), "Must define deps") - assert(defined(invoker.input), "Must define input binary file") - assert(defined(invoker.output), "Must define output assembly file") - assert(defined(invoker.symbol), "Must define symbol name") - assert(defined(invoker.executable), "Must define boolean executable") - - action(target_name) { - deps = invoker.deps - script = "//third_party/dart/runtime/tools/bin_to_assembly.py" - args = [ - "--input", - rebase_path(invoker.input), - "--output", - rebase_path(invoker.output), - "--symbol_name", - invoker.symbol, - "--target_os", - current_os, - ] - if (invoker.executable) { - args += [ "--executable" ] - } - inputs = [ - script, - invoker.input, - ] - outputs = [ - invoker.output, - ] - } + deps = [ + ":generate_dart_ui", + "//third_party/dart/runtime/bin:gen_snapshot($host_toolchain)", + ] + depfile = "$target_gen_dir/core_snapshot.d" + + inputs = [ + "//third_party/dart/runtime/tools/create_snapshot_bin.py", + snapshot_dart, + ] + dart_ui_files + if (is_fuchsia) { + inputs += [ "fuchsia_compilation_trace.txt" ] } - bin_to_assembly("vm_snapshot_data_assembly") { - deps = [ - ":generate_snapshot_bin", - ] - input = "$target_gen_dir/vm_isolate_snapshot.bin" - output = "$target_gen_dir/vm_snapshot_data.S" - symbol = "kDartVmSnapshotData" - executable = false - } + vm_snapshot_data = "$target_gen_dir/vm_isolate_snapshot.bin" + vm_snapshot_instructions = "$target_gen_dir/vm_snapshot_instructions.bin" + isolate_snapshot_data = "$target_gen_dir/isolate_snapshot.bin" + isolate_snapshot_instructions = + "$target_gen_dir/isolate_snapshot_instructions.bin" + outputs = [ + vm_snapshot_data, + vm_snapshot_instructions, + isolate_snapshot_data, + isolate_snapshot_instructions, + ] - bin_to_assembly("vm_snapshot_instructions_assembly") { - deps = [ - ":generate_snapshot_bin", - ] - input = "$target_gen_dir/vm_snapshot_instructions.bin" - output = "$target_gen_dir/vm_snapshot_instructions.S" - symbol = "kDartVmSnapshotInstructions" - executable = true - } + rebased_dart_ui_path = rebase_path(dart_ui_path) + + gen_snapshot_dir = get_label_info( + "//third_party/dart/runtime/bin:gen_snapshot($host_toolchain)", + "root_out_dir") + script = "//third_party/dart/runtime/tools/create_snapshot_bin.py" + + args = [ + "--executable", + rebase_path("$gen_snapshot_dir/gen_snapshot"), + "--script", + rebase_path(snapshot_dart), + "--snapshot_kind", + snapshot_kind, + "--vm_flag", + "--await_is_keyword", + "--vm_flag", + "--enable_mirrors=false", + "--vm_output_bin", + rebase_path(vm_snapshot_data, root_build_dir), + "--vm_instructions_output_bin", + rebase_path(vm_snapshot_instructions, root_build_dir), + "--isolate_output_bin", + rebase_path(isolate_snapshot_data, root_build_dir), + "--isolate_instructions_output_bin", + rebase_path(isolate_snapshot_instructions, root_build_dir), + "--url_mapping=dart:ui,$rebased_dart_ui_path", + "--vm_flag", + "--dependencies=" + rebase_path(depfile), + ] - bin_to_assembly("isolate_snapshot_data_assembly") { - deps = [ - ":generate_snapshot_bin", + if (is_debug) { + args += [ + "--vm_flag", + "--enable_asserts", + "--vm_flag", + "--enable_type_checks", + "--vm_flag", + "--error_on_bad_type", + "--vm_flag", + "--error_on_bad_override", ] - input = "$target_gen_dir/isolate_snapshot.bin" - output = "$target_gen_dir/isolate_snapshot_data.S" - symbol = "kDartIsolateSnapshotData" - executable = false } - bin_to_assembly("isolate_snapshot_instructions_assembly") { - deps = [ - ":generate_snapshot_bin", + if (is_fuchsia) { + inputs += zircon_sdk_ext_files + mozart_dart_sdk_ext_files + zircon_path = rebase_path(zircon_sdk_ext_lib) + fuchsia_path = rebase_path(fuchsia_sdk_ext_lib) + mozart_internal_path = rebase_path(mozart_dart_sdk_ext_lib) + args += [ + "--url_mapping=dart:zircon,$zircon_path", + "--url_mapping=dart:fuchsia,$fuchsia_path", + "--url_mapping=dart:mozart.internal,$mozart_internal_path", + "--load_compilation_trace", + rebase_path("fuchsia_compilation_trace.txt"), ] - input = "$target_gen_dir/isolate_snapshot_instructions.bin" - output = "$target_gen_dir/isolate_snapshot_instructions.S" - symbol = "kDartIsolateSnapshotInstructions" - executable = true } +} - source_set("snapshot") { - deps = [ - ":isolate_snapshot_data_assembly", - ":isolate_snapshot_instructions_assembly", - ":vm_snapshot_data_assembly", - ":vm_snapshot_instructions_assembly", +# Generates an assembly file defining a given symbol with the bytes from a +# binary file. Places the symbol in a text section if 'executable' is true, +# otherwise places the symbol in a read-only data section. +template("bin_to_assembly") { + assert(defined(invoker.deps), "Must define deps") + assert(defined(invoker.input), "Must define input binary file") + assert(defined(invoker.output), "Must define output assembly file") + assert(defined(invoker.symbol), "Must define symbol name") + assert(defined(invoker.executable), "Must define boolean executable") + + action(target_name) { + deps = invoker.deps + script = "//third_party/dart/runtime/tools/bin_to_assembly.py" + args = [ + "--input", + rebase_path(invoker.input), + "--output", + rebase_path(invoker.output), + "--symbol_name", + invoker.symbol, + "--target_os", + current_os, ] - sources = [ - "$target_gen_dir/isolate_snapshot_data.S", - "$target_gen_dir/isolate_snapshot_instructions.S", - "$target_gen_dir/vm_snapshot_data.S", - "$target_gen_dir/vm_snapshot_instructions.S", + if (invoker.executable) { + args += [ "--executable" ] + } + inputs = [ + script, + invoker.input, + ] + outputs = [ + invoker.output, ] } } +bin_to_assembly("vm_snapshot_data_assembly") { + deps = [ + ":generate_snapshot_bin", + ] + input = "$target_gen_dir/vm_isolate_snapshot.bin" + output = "$target_gen_dir/vm_snapshot_data.S" + symbol = "kDartVmSnapshotData" + executable = false +} + +bin_to_assembly("vm_snapshot_instructions_assembly") { + deps = [ + ":generate_snapshot_bin", + ] + input = "$target_gen_dir/vm_snapshot_instructions.bin" + output = "$target_gen_dir/vm_snapshot_instructions.S" + symbol = "kDartVmSnapshotInstructions" + executable = true +} + +bin_to_assembly("isolate_snapshot_data_assembly") { + deps = [ + ":generate_snapshot_bin", + ] + input = "$target_gen_dir/isolate_snapshot.bin" + output = "$target_gen_dir/isolate_snapshot_data.S" + symbol = "kDartIsolateSnapshotData" + executable = false +} + +bin_to_assembly("isolate_snapshot_instructions_assembly") { + deps = [ + ":generate_snapshot_bin", + ] + input = "$target_gen_dir/isolate_snapshot_instructions.bin" + output = "$target_gen_dir/isolate_snapshot_instructions.S" + symbol = "kDartIsolateSnapshotInstructions" + executable = true +} + +source_set("snapshot") { + deps = [ + ":isolate_snapshot_data_assembly", + ":isolate_snapshot_instructions_assembly", + ":vm_snapshot_data_assembly", + ":vm_snapshot_instructions_assembly", + ] + sources = [ + "$target_gen_dir/isolate_snapshot_data.S", + "$target_gen_dir/isolate_snapshot_instructions.S", + "$target_gen_dir/vm_snapshot_data.S", + "$target_gen_dir/vm_snapshot_instructions.S", + ] +} + compile_platform("non_strong_platform") { libraries_specification_uri = "libraries.json" @@ -228,28 +282,22 @@ template("generate_entry_points_json_with_gen_snapshot") { output = invoker.output tool = "//third_party/dart/runtime/bin:gen_snapshot" - inputs = [ input ] + extra_inputs + inputs = [ + input, + ] + extra_inputs outputs = [ output, - - # Though they are not consumed, GN needs to know to create the output directory. - "$target_gen_dir/dummy.vm_data.snapshot", - "$target_gen_dir/dummy.vm_instr.snapshot", - "$target_gen_dir/dummy.isolate_data.snapshot", - "$target_gen_dir/dummy.isolate_instr.snapshot", ] args = [ - "--print-precompiler-entry-points=" + rebase_path(output), - "--snapshot-kind=app-aot-blobs", - "--vm_snapshot_data=" + - rebase_path("$target_gen_dir/dummy.vm_data.snapshot"), - "--vm_snapshot_instructions=" + - rebase_path("$target_gen_dir/dummy.vm_instr.snapshot"), - "--isolate_snapshot_data=" + - rebase_path("$target_gen_dir/dummy.isolate_data.snapshot"), - "--isolate_snapshot_instructions=" + - rebase_path("$target_gen_dir/dummy.isolate_instr.snapshot"), - ] + extra_args + [ rebase_path(input) ] + "--print-precompiler-entry-points=" + rebase_path(output), + "--snapshot-kind=app-aot-blobs", + "--vm_snapshot_data=" + rebase_path("$target_gen_dir/dummy.vm_data.snapshot"), + "--vm_snapshot_instructions=" + rebase_path("$target_gen_dir/dummy.vm_instr.snapshot"), + "--isolate_snapshot_data=" + rebase_path("$target_gen_dir/dummy.isolate_data.snapshot"), + "--isolate_snapshot_instructions=" + rebase_path("$target_gen_dir/dummy.isolate_instr.snapshot"), + ] + extra_args + [ + rebase_path(input), + ] } } diff --git a/runtime/dart_isolate.cc b/runtime/dart_isolate.cc index 34962593ea1f56e1e34b89d06ab375bf2db1f077..e48c542c11d6153a69fba3e822bba2706878ee1f 100644 --- a/runtime/dart_isolate.cc +++ b/runtime/dart_isolate.cc @@ -282,12 +282,20 @@ bool DartIsolate::PrepareForRunningFromPrecompiledCode() { return true; } -bool DartIsolate::LoadKernel(std::shared_ptr mapping, - bool last_piece) { - if (!Dart_IsKernel(mapping->GetMapping(), mapping->GetSize())) { +bool DartIsolate::LoadScriptSnapshot( + std::shared_ptr mapping, + bool last_piece) { + FML_CHECK(last_piece) << "Script snapshots cannot be divided"; + if (tonic::LogIfError(Dart_LoadScriptFromSnapshot(mapping->GetMapping(), + mapping->GetSize()))) { return false; } + return true; +} +bool DartIsolate::LoadKernelSnapshot( + std::shared_ptr mapping, + bool last_piece) { // Mapping must be retained until isolate shutdown. kernel_buffers_.push_back(mapping); @@ -309,11 +317,21 @@ bool DartIsolate::LoadKernel(std::shared_ptr mapping, return true; } +bool DartIsolate::LoadSnapshot(std::shared_ptr mapping, + bool last_piece) { + if (Dart_IsKernel(mapping->GetMapping(), mapping->GetSize())) { + return LoadKernelSnapshot(std::move(mapping), last_piece); + } else { + return LoadScriptSnapshot(std::move(mapping), last_piece); + } + return false; +} + FML_WARN_UNUSED_RESULT -bool DartIsolate::PrepareForRunningFromKernel( +bool DartIsolate::PrepareForRunningFromSnapshot( std::shared_ptr mapping, bool last_piece) { - TRACE_EVENT0("flutter", "DartIsolate::PrepareForRunningFromKernel"); + TRACE_EVENT0("flutter", "DartIsolate::PrepareForRunningFromSnapshot"); if (phase_ != Phase::LibrariesSetup) { return false; } @@ -331,7 +349,7 @@ bool DartIsolate::PrepareForRunningFromKernel( // Use root library provided by kernel in favor of one provided by snapshot. Dart_SetRootLibrary(Dart_Null()); - if (!LoadKernel(mapping, last_piece)) { + if (!LoadSnapshot(mapping, last_piece)) { return false; } @@ -349,7 +367,61 @@ bool DartIsolate::PrepareForRunningFromKernel( } child_isolate_preparer_ = [mapping](DartIsolate* isolate) { - return isolate->PrepareForRunningFromKernel(mapping); + return isolate->PrepareForRunningFromSnapshot(mapping); + }; + phase_ = Phase::Ready; + return true; +} + +bool DartIsolate::PrepareForRunningFromSource( + const std::string& main_source_file, + const std::string& packages) { + TRACE_EVENT0("flutter", "DartIsolate::PrepareForRunningFromSource"); + if (phase_ != Phase::LibrariesSetup) { + return false; + } + + if (DartVM::IsRunningPrecompiledCode()) { + return false; + } + + if (main_source_file.empty()) { + return false; + } + + tonic::DartState::Scope scope(this); + + if (!Dart_IsNull(Dart_RootLibrary())) { + return false; + } + + auto& loader = file_loader(); + + if (!packages.empty()) { + auto packages_absolute_path = fml::paths::AbsolutePath(packages); + FML_DLOG(INFO) << "Loading from packages: " << packages_absolute_path; + if (!loader.LoadPackagesMap(packages_absolute_path)) { + return false; + } + } + + auto main_source_absolute_path = fml::paths::AbsolutePath(main_source_file); + FML_DLOG(INFO) << "Loading from source: " << main_source_absolute_path; + + if (tonic::LogIfError(loader.LoadScript(main_source_absolute_path))) { + return false; + } + + if (Dart_IsNull(Dart_RootLibrary())) { + return false; + } + + if (!MarkIsolateRunnable()) { + return false; + } + + child_isolate_preparer_ = [main_source_file, packages](DartIsolate* isolate) { + return isolate->PrepareForRunningFromSource(main_source_file, packages); }; phase_ = Phase::Ready; return true; @@ -536,11 +608,22 @@ Dart_Isolate DartIsolate::DartCreateAndStartServiceIsolate( return nullptr; } + // The engine never holds a strong reference to the VM service isolate. Since + // we are about to lose our last weak reference to it, start the VM service + // while we have this reference. + const bool isolate_snapshot_is_dart_2 = Dart_IsDart2Snapshot( + vm->GetIsolateSnapshot()->GetData()->GetSnapshotPointer()); + const bool is_preview_dart2 = + (vm->GetPlatformKernel().GetSize() > 0) || isolate_snapshot_is_dart_2; + const bool running_from_sources = + !DartVM::IsRunningPrecompiledCode() && !is_preview_dart2; + tonic::DartState::Scope scope(service_isolate); if (!DartServiceIsolate::Startup( settings.ipv6 ? "::1" : "127.0.0.1", // server IP address settings.observatory_port, // server observatory port tonic::DartState::HandleLibraryTag, // embedder library tag handler + running_from_sources, // running from source code false, // disable websocket origin check error // error (out) )) { @@ -644,20 +727,39 @@ DartIsolate::CreateDartVMAndEmbedderObjectPair( Dart_IsolateFlagsInitialize(&nonnull_flags); flags = &nonnull_flags; } - flags->use_dart_frontend = true; + bool dart2 = (vm->GetPlatformKernel().GetSize() > 0) || + Dart_IsDart2Snapshot((*embedder_isolate) + ->GetIsolateSnapshot() + ->GetData() + ->GetSnapshotPointer()); + flags->use_dart_frontend = dart2; // Create the Dart VM isolate and give it the embedder object as the baton. - Dart_Isolate isolate = Dart_CreateIsolate( - advisory_script_uri, // - advisory_script_entrypoint, // - (*embedder_isolate) - ->GetIsolateSnapshot() - ->GetData() - ->GetSnapshotPointer(), - (*embedder_isolate)->GetIsolateSnapshot()->GetInstructionsIfPresent(), - (*embedder_isolate)->GetSharedSnapshot()->GetDataIfPresent(), - (*embedder_isolate)->GetSharedSnapshot()->GetInstructionsIfPresent(), - flags, embedder_isolate.get(), error); + Dart_Isolate isolate = + (vm->GetPlatformKernel().GetSize() > 0) + ? Dart_CreateIsolateFromKernel( + advisory_script_uri, // + advisory_script_entrypoint, // + vm->GetPlatformKernel().GetMapping(), // + vm->GetPlatformKernel().GetSize(), // + flags, // + embedder_isolate.get(), // + error // + ) + : Dart_CreateIsolate( + advisory_script_uri, advisory_script_entrypoint, + (*embedder_isolate) + ->GetIsolateSnapshot() + ->GetData() + ->GetSnapshotPointer(), + (*embedder_isolate) + ->GetIsolateSnapshot() + ->GetInstructionsIfPresent(), + (*embedder_isolate)->GetSharedSnapshot()->GetDataIfPresent(), + (*embedder_isolate) + ->GetSharedSnapshot() + ->GetInstructionsIfPresent(), + flags, embedder_isolate.get(), error); if (isolate == nullptr) { FML_DLOG(ERROR) << *error; diff --git a/runtime/dart_isolate.h b/runtime/dart_isolate.h index f2167364effdd2416ced4a7ceef238350edea624..df9a9f66d1b46e5256cb3907721cb562299efcdd 100644 --- a/runtime/dart_isolate.h +++ b/runtime/dart_isolate.h @@ -68,8 +68,13 @@ class DartIsolate : public UIDartState { bool PrepareForRunningFromPrecompiledCode(); FML_WARN_UNUSED_RESULT - bool PrepareForRunningFromKernel(std::shared_ptr kernel, - bool last_piece = true); + bool PrepareForRunningFromSnapshot( + std::shared_ptr snapshot, + bool last_piece = true); + + FML_WARN_UNUSED_RESULT + bool PrepareForRunningFromSource(const std::string& main_source_file, + const std::string& packages); FML_WARN_UNUSED_RESULT bool Run(const std::string& entrypoint); @@ -91,7 +96,12 @@ class DartIsolate : public UIDartState { std::weak_ptr GetWeakIsolatePtr(); private: - bool LoadKernel(std::shared_ptr mapping, bool last_piece); + bool LoadScriptSnapshot(std::shared_ptr mapping, + bool last_piece); + bool LoadKernelSnapshot(std::shared_ptr mapping, + bool last_piece); + bool LoadSnapshot(std::shared_ptr mapping, + bool last_piece); class AutoFireClosure { public: diff --git a/runtime/dart_isolate_unittests.cc b/runtime/dart_isolate_unittests.cc index cb7797abdcb74b921e6accb4d59604108507fd27..02cbbaf8cf5f227f4f16d0301e58911002bddd8c 100644 --- a/runtime/dart_isolate_unittests.cc +++ b/runtime/dart_isolate_unittests.cc @@ -46,4 +46,70 @@ TEST_F(DartIsolateTest, RootIsolateCreationAndShutdown) { ASSERT_TRUE(root_isolate->Shutdown()); } +TEST_F(DartIsolateTest, IsolateCanAssociateSnapshot) { + Settings settings = {}; + settings.task_observer_add = [](intptr_t, fml::closure) {}; + settings.task_observer_remove = [](intptr_t) {}; + auto vm = DartVM::ForProcess(settings); + ASSERT_TRUE(vm); + TaskRunners task_runners(CURRENT_TEST_NAME, // + GetCurrentTaskRunner(), // + GetCurrentTaskRunner(), // + GetCurrentTaskRunner(), // + GetCurrentTaskRunner() // + ); + auto weak_isolate = DartIsolate::CreateRootIsolate( + vm.get(), // vm + vm->GetIsolateSnapshot(), // isolate snapshot + vm->GetSharedSnapshot(), // shared snapshot + std::move(task_runners), // task runners + nullptr, // window + {}, // resource context + nullptr, // unref qeueue + "main.dart", // advisory uri + "main" // advisory entrypoint + ); + auto root_isolate = weak_isolate.lock(); + ASSERT_TRUE(root_isolate); + ASSERT_EQ(root_isolate->GetPhase(), DartIsolate::Phase::LibrariesSetup); + ASSERT_TRUE(root_isolate->PrepareForRunningFromSource( + testing::GetFixturesPath() + std::string{"/simple_main.dart"}, "")); + ASSERT_EQ(root_isolate->GetPhase(), DartIsolate::Phase::Ready); + ASSERT_TRUE(root_isolate->Shutdown()); +} + +TEST_F(DartIsolateTest, CanResolveAndInvokeMethod) { + Settings settings = {}; + settings.task_observer_add = [](intptr_t, fml::closure) {}; + settings.task_observer_remove = [](intptr_t) {}; + auto vm = DartVM::ForProcess(settings); + ASSERT_TRUE(vm); + TaskRunners task_runners(CURRENT_TEST_NAME, // + GetCurrentTaskRunner(), // + GetCurrentTaskRunner(), // + GetCurrentTaskRunner(), // + GetCurrentTaskRunner() // + ); + auto weak_isolate = DartIsolate::CreateRootIsolate( + vm.get(), // vm + vm->GetIsolateSnapshot(), // isolate snapshot + vm->GetSharedSnapshot(), // shared snapshot + std::move(task_runners), // task runners + nullptr, // window + {}, // resource context + nullptr, // unref qeueue + "main.dart", // advisory uri + "main" // advisory entrypoint + ); + auto root_isolate = weak_isolate.lock(); + ASSERT_TRUE(root_isolate); + ASSERT_EQ(root_isolate->GetPhase(), DartIsolate::Phase::LibrariesSetup); + ASSERT_TRUE(root_isolate->PrepareForRunningFromSource( + testing::GetFixturesPath() + std::string{"/simple_main.dart"}, "")); + ASSERT_EQ(root_isolate->GetPhase(), DartIsolate::Phase::Ready); + ASSERT_TRUE(root_isolate->Run("simple_main")); + ASSERT_EQ(root_isolate->GetPhase(), DartIsolate::Phase::Running); + ASSERT_TRUE(root_isolate->Shutdown()); +} + } // namespace blink diff --git a/runtime/dart_service_isolate.cc b/runtime/dart_service_isolate.cc index 05da4c48fc2dd70c5f7be99270070a3f6d4eedd4..d1a699869959a161af7e60276366d699da4f2f6c 100644 --- a/runtime/dart_service_isolate.cc +++ b/runtime/dart_service_isolate.cc @@ -26,11 +26,21 @@ return false; \ } +#define kLibrarySourceNamePrefix "/vmservice" +static const char* kServiceIsolateScript = "vmservice_io.dart"; + +namespace flutter { +namespace runtime { +extern ResourcesEntry __flutter_embedded_service_isolate_resources_[]; +} +} // namespace flutter + namespace blink { namespace { static Dart_LibraryTagHandler g_embedder_tag_handler; static tonic::DartLibraryNatives* g_natives; +static EmbedderResources* g_resources; static std::string observatory_uri_; Dart_NativeFunction GetNativeFunction(Dart_Handle name, @@ -47,6 +57,13 @@ const uint8_t* GetSymbol(Dart_NativeFunction native_function) { } // namespace +void DartServiceIsolate::TriggerResourceLoad(Dart_NativeArguments args) { + Dart_Handle library = Dart_RootLibrary(); + FML_DCHECK(!Dart_IsError(library)); + Dart_Handle result = LoadResources(library); + FML_DCHECK(!Dart_IsError(result)); +} + void DartServiceIsolate::NotifyServerState(Dart_NativeArguments args) { Dart_Handle exception = nullptr; std::string uri = @@ -67,6 +84,7 @@ void DartServiceIsolate::Shutdown(Dart_NativeArguments args) { bool DartServiceIsolate::Startup(std::string server_ip, intptr_t server_port, Dart_LibraryTagHandler embedder_tag_handler, + bool running_from_sources, bool disable_origin_check, char** error) { Dart_Isolate isolate = Dart_CurrentIsolate(); @@ -85,13 +103,36 @@ bool DartServiceIsolate::Startup(std::string server_ip, }); } - Dart_Handle uri = Dart_NewStringFromCString("dart:vmservice_io"); - Dart_Handle library = Dart_LookupLibrary(uri); - SHUTDOWN_ON_ERROR(library); - Dart_Handle result = Dart_SetRootLibrary(library); - SHUTDOWN_ON_ERROR(result); - result = Dart_SetNativeResolver(library, GetNativeFunction, GetSymbol); - SHUTDOWN_ON_ERROR(result); + if (!g_resources) { + g_resources = new EmbedderResources( + &flutter::runtime::__flutter_embedded_service_isolate_resources_[0]); + } + + Dart_Handle result; + + if (running_from_sources) { + // Use our own library tag handler when loading service isolate sources. + Dart_SetLibraryTagHandler(DartServiceIsolate::LibraryTagHandler); + // Load main script. + Dart_Handle library = LoadScript(kServiceIsolateScript); + FML_DCHECK(library != Dart_Null()); + SHUTDOWN_ON_ERROR(library); + // Setup native entry resolution. + result = Dart_SetNativeResolver(library, GetNativeFunction, GetSymbol); + + SHUTDOWN_ON_ERROR(result); + // Finalize loading. + result = Dart_FinalizeLoading(false); + SHUTDOWN_ON_ERROR(result); + } else { + Dart_Handle uri = Dart_NewStringFromCString("dart:vmservice_io"); + Dart_Handle library = Dart_LookupLibrary(uri); + SHUTDOWN_ON_ERROR(library); + result = Dart_SetRootLibrary(library); + SHUTDOWN_ON_ERROR(result); + result = Dart_SetNativeResolver(library, GetNativeFunction, GetSymbol); + SHUTDOWN_ON_ERROR(result); + } // Make runnable. Dart_ExitScope(); @@ -105,7 +146,7 @@ bool DartServiceIsolate::Startup(std::string server_ip, Dart_EnterIsolate(isolate); Dart_EnterScope(); - library = Dart_RootLibrary(); + Dart_Handle library = Dart_RootLibrary(); SHUTDOWN_ON_ERROR(library); // Set the HTTP server's ip. @@ -133,4 +174,115 @@ bool DartServiceIsolate::Startup(std::string server_ip, return true; } +Dart_Handle DartServiceIsolate::GetSource(const char* name) { + const intptr_t kBufferSize = 512; + char buffer[kBufferSize]; + snprintf(&buffer[0], kBufferSize - 1, "%s/%s", kLibrarySourceNamePrefix, + name); + const char* vmservice_source = NULL; + int r = g_resources->ResourceLookup(buffer, &vmservice_source); + FML_DCHECK(r != EmbedderResources::kNoSuchInstance); + return Dart_NewStringFromCString(vmservice_source); +} + +Dart_Handle DartServiceIsolate::LoadScript(const char* name) { + Dart_Handle url = Dart_NewStringFromCString("dart:vmservice_io"); + Dart_Handle source = GetSource(name); + return Dart_LoadScript(url, Dart_Null(), source, 0, 0); +} + +Dart_Handle DartServiceIsolate::LoadSource(Dart_Handle library, + const char* name) { + Dart_Handle url = Dart_NewStringFromCString(name); + Dart_Handle source = GetSource(name); + return Dart_LoadSource(library, url, Dart_Null(), source, 0, 0); +} + +Dart_Handle DartServiceIsolate::LoadResource(Dart_Handle library, + const char* resource_name) { + // Prepare for invoke call. + Dart_Handle name = Dart_NewStringFromCString(resource_name); + RETURN_ERROR_HANDLE(name); + const char* data_buffer = NULL; + int data_buffer_length = + g_resources->ResourceLookup(resource_name, &data_buffer); + FML_DCHECK(data_buffer_length != EmbedderResources::kNoSuchInstance); + Dart_Handle data_list = + Dart_NewTypedData(Dart_TypedData_kUint8, data_buffer_length); + RETURN_ERROR_HANDLE(data_list); + Dart_TypedData_Type type = Dart_TypedData_kInvalid; + void* data_list_buffer = NULL; + intptr_t data_list_buffer_length = 0; + Dart_Handle result = Dart_TypedDataAcquireData( + data_list, &type, &data_list_buffer, &data_list_buffer_length); + RETURN_ERROR_HANDLE(result); + FML_DCHECK(data_buffer_length == data_list_buffer_length); + FML_DCHECK(data_list_buffer != NULL); + FML_DCHECK(type = Dart_TypedData_kUint8); + memmove(data_list_buffer, &data_buffer[0], data_buffer_length); + result = Dart_TypedDataReleaseData(data_list); + RETURN_ERROR_HANDLE(result); + + // Make invoke call. + const intptr_t kNumArgs = 2; + Dart_Handle args[kNumArgs] = {name, data_list}; + result = Dart_Invoke(library, Dart_NewStringFromCString("_addResource"), + kNumArgs, args); + return result; +} + +Dart_Handle DartServiceIsolate::LoadResources(Dart_Handle library) { + Dart_Handle result = Dart_Null(); + intptr_t prefixLen = strlen(kLibrarySourceNamePrefix); + for (intptr_t i = 0; g_resources->Path(i) != NULL; i++) { + const char* path = g_resources->Path(i); + // If it doesn't begin with kLibrarySourceNamePrefix it is a frontend + // resource. + if (strncmp(path, kLibrarySourceNamePrefix, prefixLen) != 0) { + result = LoadResource(library, path); + if (Dart_IsError(result)) { + break; + } + } + } + return result; +} + +Dart_Handle DartServiceIsolate::LibraryTagHandler(Dart_LibraryTag tag, + Dart_Handle library, + Dart_Handle url) { + if (!Dart_IsLibrary(library)) { + return Dart_NewApiError("not a library"); + } + if (!Dart_IsString(url)) { + return Dart_NewApiError("url is not a string"); + } + const char* url_string = NULL; + Dart_Handle result = Dart_StringToCString(url, &url_string); + if (Dart_IsError(result)) { + return result; + } + Dart_Handle library_url = Dart_LibraryUrl(library); + const char* library_url_string = NULL; + result = Dart_StringToCString(library_url, &library_url_string); + if (Dart_IsError(result)) { + return result; + } + if (tag == Dart_kImportTag) { + // Embedder handles all requests for external libraries. + return g_embedder_tag_handler(tag, library, url); + } + FML_DCHECK((tag == Dart_kSourceTag) || (tag == Dart_kCanonicalizeUrl)); + if (tag == Dart_kCanonicalizeUrl) { + // url is already canonicalized. + return url; + } + // Get source from builtin resources. + Dart_Handle source = GetSource(url_string); + if (Dart_IsError(source)) { + return source; + } + return Dart_LoadSource(library, url, Dart_Null(), source, 0, 0); +} + } // namespace blink diff --git a/runtime/dart_service_isolate.h b/runtime/dart_service_isolate.h index 3d672dc83bb4cdf1a5f1eae3293d1c186b97ead6..59a02e2e9d4951a685f7ccfee961e46e1bd0abf7 100644 --- a/runtime/dart_service_isolate.h +++ b/runtime/dart_service_isolate.h @@ -16,6 +16,7 @@ class DartServiceIsolate { static bool Startup(std::string server_ip, intptr_t server_port, Dart_LibraryTagHandler embedder_tag_handler, + bool running_from_sources, bool disable_origin_check, char** error); @@ -23,8 +24,21 @@ class DartServiceIsolate { private: // Native entries. + static void TriggerResourceLoad(Dart_NativeArguments args); static void NotifyServerState(Dart_NativeArguments args); static void Shutdown(Dart_NativeArguments args); + + // Script loading. + static Dart_Handle GetSource(const char* name); + static Dart_Handle LoadScript(const char* name); + static Dart_Handle LoadSource(Dart_Handle library, const char* name); + static Dart_Handle LibraryTagHandler(Dart_LibraryTag tag, + Dart_Handle library, + Dart_Handle url); + + // Observatory resource loading. + static Dart_Handle LoadResources(Dart_Handle library); + static Dart_Handle LoadResource(Dart_Handle library, const char* name); }; } // namespace blink diff --git a/runtime/dart_vm.cc b/runtime/dart_vm.cc index 4fa0d3a3ea1ba6d871f67ac2fcc311754a973ec7..b263914538217b3a53a07723b1198ccf665ea47e 100644 --- a/runtime/dart_vm.cc +++ b/runtime/dart_vm.cc @@ -310,6 +310,8 @@ DartVM::DartVM(const Settings& settings, vm_snapshot_(std::move(vm_snapshot)), isolate_snapshot_(std::move(isolate_snapshot)), shared_snapshot_(std::move(shared_snapshot)), + platform_kernel_mapping_( + std::make_unique(settings.platform_kernel_path)), weak_factory_(this) { TRACE_EVENT0("flutter", "DartVMInitializer"); FML_DLOG(INFO) << "Attempting Dart VM launch for mode: " @@ -366,11 +368,17 @@ DartVM::DartVM(const Settings& settings, arraysize(kDartWriteProtectCodeArgs)); #endif - const bool is_preview_dart2 = + const bool isolate_snapshot_is_dart_2 = Dart_IsDart2Snapshot(isolate_snapshot_->GetData()->GetSnapshotPointer()); + const bool is_preview_dart2 = + (platform_kernel_mapping_->GetSize() > 0) || isolate_snapshot_is_dart_2; + FML_DLOG(INFO) << "Dart 2 " << (is_preview_dart2 ? "is" : "is NOT") - << " enabled."; + << " enabled. Platform kernel: " + << static_cast(platform_kernel_mapping_->GetSize() > 0) + << " Isolate Snapshot is Dart 2: " + << isolate_snapshot_is_dart_2; if (is_preview_dart2) { PushBackAll(&args, kDartStrongModeArgs, arraysize(kDartStrongModeArgs)); @@ -477,6 +485,10 @@ const Settings& DartVM::GetSettings() const { return settings_; } +const fml::Mapping& DartVM::GetPlatformKernel() const { + return *platform_kernel_mapping_.get(); +} + const DartSnapshot& DartVM::GetVMSnapshot() const { return *vm_snapshot_.get(); } diff --git a/runtime/dart_vm.h b/runtime/dart_vm.h index b853f026c328f901b96465c33f67f11602e29415..ebb41edadb479270d81fae9740f7cea21f720007 100644 --- a/runtime/dart_vm.h +++ b/runtime/dart_vm.h @@ -42,6 +42,8 @@ class DartVM : public fml::RefCountedThreadSafe { const Settings& GetSettings() const; + const fml::Mapping& GetPlatformKernel() const; + const DartSnapshot& GetVMSnapshot() const; IsolateNameServer* GetIsolateNameServer(); @@ -60,6 +62,7 @@ class DartVM : public fml::RefCountedThreadSafe { IsolateNameServer isolate_name_server_; const fml::RefPtr isolate_snapshot_; const fml::RefPtr shared_snapshot_; + std::unique_ptr platform_kernel_mapping_; ServiceProtocol service_protocol_; fml::WeakPtrFactory weak_factory_; diff --git a/runtime/dart_vm_unittests.cc b/runtime/dart_vm_unittests.cc index 94d5dadaaec1f25176b9c6b8525a5ee9f3f2b14f..d0e247836410b2a297ac37527b6874d4661d5d73 100644 --- a/runtime/dart_vm_unittests.cc +++ b/runtime/dart_vm_unittests.cc @@ -15,6 +15,7 @@ TEST(DartVM, SimpleInitialization) { ASSERT_TRUE(vm); ASSERT_EQ(vm, DartVM::ForProcess(settings)); ASSERT_FALSE(DartVM::IsRunningPrecompiledCode()); + ASSERT_EQ(vm->GetPlatformKernel().GetSize(), 0u); } TEST(DartVM, SimpleIsolateNameServer) { diff --git a/shell/common/engine.cc b/shell/common/engine.cc index b79dbfae33555c3dba6b97c4fae041d4a3054a33..1b9d3657b6ece6d62a040d60319679417974a9a9 100644 --- a/shell/common/engine.cc +++ b/shell/common/engine.cc @@ -47,6 +47,7 @@ Engine::Engine(Delegate& delegate, : delegate_(delegate), settings_(std::move(settings)), animator_(std::move(animator)), + load_script_error_(tonic::kNoError), activity_running_(false), have_surface_(false), weak_factory_(this) { @@ -204,6 +205,10 @@ tonic::DartErrorHandleType Engine::GetUIIsolateLastError() { return runtime_controller_->GetLastError(); } +tonic::DartErrorHandleType Engine::GetLoadScriptError() { + return load_script_error_; +} + void Engine::OnOutputSurfaceCreated() { have_surface_ = true; StartAnimatorIfPossible(); diff --git a/shell/common/engine.h b/shell/common/engine.h index f35b9ba42111380185d5ca8eb6de2982ef0d7116..259f73514b67d2f0a900c497fd903a438ddbdb80 100644 --- a/shell/common/engine.h +++ b/shell/common/engine.h @@ -79,6 +79,8 @@ class Engine final : public blink::RuntimeDelegate { tonic::DartErrorHandleType GetUIIsolateLastError(); + tonic::DartErrorHandleType GetLoadScriptError(); + std::pair GetUIIsolateReturnCode(); void OnOutputSurfaceCreated(); @@ -109,6 +111,7 @@ class Engine final : public blink::RuntimeDelegate { const blink::Settings settings_; std::unique_ptr animator_; std::unique_ptr runtime_controller_; + tonic::DartErrorHandleType load_script_error_; std::string initial_route_; blink::ViewportMetrics viewport_metrics_; fml::RefPtr asset_manager_; diff --git a/shell/common/isolate_configuration.cc b/shell/common/isolate_configuration.cc index 57c38bef9f8d8b1405546ddd6dae617342fee780..66dd53fb1b59c090b18d3776b6f783a6339a0d5c 100644 --- a/shell/common/isolate_configuration.cc +++ b/shell/common/isolate_configuration.cc @@ -39,23 +39,45 @@ class AppSnapshotIsolateConfiguration final : public IsolateConfiguration { FML_DISALLOW_COPY_AND_ASSIGN(AppSnapshotIsolateConfiguration); }; -class KernelIsolateConfiguration : public IsolateConfiguration { +class SnapshotIsolateConfiguration : public IsolateConfiguration { public: - KernelIsolateConfiguration(std::unique_ptr kernel) - : kernel_(std::move(kernel)) {} + SnapshotIsolateConfiguration(std::unique_ptr snapshot) + : snapshot_(std::move(snapshot)) {} // |shell::IsolateConfiguration| bool DoPrepareIsolate(blink::DartIsolate& isolate) override { if (blink::DartVM::IsRunningPrecompiledCode()) { return false; } - return isolate.PrepareForRunningFromKernel(std::move(kernel_)); + return isolate.PrepareForRunningFromSnapshot(std::move(snapshot_)); } private: - std::unique_ptr kernel_; + std::unique_ptr snapshot_; - FML_DISALLOW_COPY_AND_ASSIGN(KernelIsolateConfiguration); + FML_DISALLOW_COPY_AND_ASSIGN(SnapshotIsolateConfiguration); +}; + +class SourceIsolateConfiguration final : public IsolateConfiguration { + public: + SourceIsolateConfiguration(std::string main_path, std::string packages_path) + : main_path_(std::move(main_path)), + packages_path_(std::move(packages_path)) {} + + // |shell::IsolateConfiguration| + bool DoPrepareIsolate(blink::DartIsolate& isolate) override { + if (blink::DartVM::IsRunningPrecompiledCode()) { + return false; + } + return isolate.PrepareForRunningFromSource(std::move(main_path_), + std::move(packages_path_)); + } + + private: + std::string main_path_; + std::string packages_path_; + + FML_DISALLOW_COPY_AND_ASSIGN(SourceIsolateConfiguration); }; class KernelListIsolateConfiguration final : public IsolateConfiguration { @@ -72,8 +94,8 @@ class KernelListIsolateConfiguration final : public IsolateConfiguration { for (size_t i = 0; i < kernel_pieces_.size(); i++) { bool last_piece = i + 1 == kernel_pieces_.size(); - if (!isolate.PrepareForRunningFromKernel(std::move(kernel_pieces_[i]), - last_piece)) { + if (!isolate.PrepareForRunningFromSnapshot(std::move(kernel_pieces_[i]), + last_piece)) { return false; } } @@ -95,12 +117,30 @@ std::unique_ptr IsolateConfiguration::InferFromSettings( return CreateForAppSnapshot(); } + // Run from sources. + { + const auto& main = settings.main_dart_file_path; + const auto& packages = settings.packages_file_path; + if (main.size() != 0 && packages.size() != 0) { + return CreateForSource(std::move(main), std::move(packages)); + } + } + // Running from kernel snapshot. if (asset_manager) { std::unique_ptr kernel = asset_manager->GetAsMapping(settings.application_kernel_asset); if (kernel) { - return CreateForKernel(std::move(kernel)); + return CreateForSnapshot(std::move(kernel)); + } + } + + // Running from script snapshot. + if (asset_manager) { + std::unique_ptr script_snapshot = + asset_manager->GetAsMapping(settings.script_snapshot_path); + if (script_snapshot) { + return CreateForSnapshot(std::move(script_snapshot)); } } @@ -149,9 +189,16 @@ IsolateConfiguration::CreateForAppSnapshot() { return std::make_unique(); } -std::unique_ptr IsolateConfiguration::CreateForKernel( - std::unique_ptr kernel) { - return std::make_unique(std::move(kernel)); +std::unique_ptr IsolateConfiguration::CreateForSnapshot( + std::unique_ptr snapshot) { + return std::make_unique(std::move(snapshot)); +} + +std::unique_ptr IsolateConfiguration::CreateForSource( + std::string main_path, + std::string packages_path) { + return std::make_unique(std::move(main_path), + std::move(packages_path)); } std::unique_ptr IsolateConfiguration::CreateForKernelList( diff --git a/shell/common/isolate_configuration.h b/shell/common/isolate_configuration.h index 7dd54ccf3b3b7b16c52fc44dc6ea7be143388d13..ba8752273d6deb3e2f040bcb3be986b97adadc82 100644 --- a/shell/common/isolate_configuration.h +++ b/shell/common/isolate_configuration.h @@ -26,8 +26,12 @@ class IsolateConfiguration { static std::unique_ptr CreateForAppSnapshot(); - static std::unique_ptr CreateForKernel( - std::unique_ptr kernel); + static std::unique_ptr CreateForSnapshot( + std::unique_ptr snapshot); + + static std::unique_ptr CreateForSource( + std::string main_path, + std::string packages_path); static std::unique_ptr CreateForKernelList( std::vector> kernel_pieces); diff --git a/shell/common/shell.cc b/shell/common/shell.cc index 7d434cb055be4c9fb12dd19e18410d1882e6507d..59272e11c0539064858bd8b79d3a430e5a981253 100644 --- a/shell/common/shell.cc +++ b/shell/common/shell.cc @@ -875,8 +875,12 @@ bool Shell::OnServiceProtocolRunInView( auto main_script_file_mapping = std::make_unique(main_script_path, false); - auto isolate_configuration = IsolateConfiguration::CreateForKernel( - std::move(main_script_file_mapping)); + auto isolate_configuration = + blink::DartVM::IsKernelMapping(main_script_file_mapping.get()) + ? IsolateConfiguration::CreateForSnapshot( + std::move(main_script_file_mapping)) + : IsolateConfiguration::CreateForSource(main_script_path, + packages_path); RunConfiguration configuration(std::move(isolate_configuration)); diff --git a/shell/common/switches.cc b/shell/common/switches.cc index 98f0bb353015f5b2eb83faeb94540a2ffc9ea4f7..80ae36a7e57767709807595b61ca3327238a6bbf 100644 --- a/shell/common/switches.cc +++ b/shell/common/switches.cc @@ -170,6 +170,9 @@ blink::Settings SettingsFromCommandLine(const fml::CommandLine& command_line) { command_line.GetOptionValue(FlagForSwitch(Switch::FlutterAssetsDir), &settings.assets_path); + command_line.GetOptionValue(FlagForSwitch(Switch::Snapshot), + &settings.script_snapshot_path); + command_line.GetOptionValue(FlagForSwitch(Switch::MainDartFile), &settings.main_dart_file_path); diff --git a/shell/common/switches.h b/shell/common/switches.h index 644b02f2cbce582401311a17583d932331e1b678..6bae9047e0e3d18a7216056a17cb1c575b38a091 100644 --- a/shell/common/switches.h +++ b/shell/common/switches.h @@ -93,6 +93,7 @@ DEF_SWITCH(Help, "help", "Display this help text.") DEF_SWITCH(LogTag, "log-tag", "Tag associated with log messages.") DEF_SWITCH(MainDartFile, "dart-main", "The path to the main Dart file.") DEF_SWITCH(Packages, "packages", "Specify the path to the packages.") +DEF_SWITCH(Snapshot, "snapshot-blob", "Specify the path to the snapshot blob") DEF_SWITCH(StartPaused, "start-paused", "Start the application paused in the Dart debugger.") diff --git a/shell/platform/android/flutter_main.cc b/shell/platform/android/flutter_main.cc index 0bcf75d76fecaa8a87dc4329abd7c8e6c16f647e..b8931e6e46753e75e464660c7d1730932bcc507a 100644 --- a/shell/platform/android/flutter_main.cc +++ b/shell/platform/android/flutter_main.cc @@ -66,11 +66,16 @@ void FlutterMain::Init(JNIEnv* env, if (!blink::DartVM::IsRunningPrecompiledCode()) { // Check to see if the appropriate kernel files are present and configure // settings accordingly. + auto platform_kernel_path = + fml::paths::JoinPaths({settings.assets_path, "platform_strong.dill"}); auto application_kernel_path = fml::paths::JoinPaths({settings.assets_path, "kernel_blob.bin"}); if (fml::IsFile(application_kernel_path)) { settings.application_kernel_asset = application_kernel_path; + if (fml::IsFile(platform_kernel_path)) { + settings.platform_kernel_path = platform_kernel_path; + } } } diff --git a/shell/platform/android/io/flutter/view/FlutterMain.java b/shell/platform/android/io/flutter/view/FlutterMain.java index 198bcade69ae826c7b51f1f6d1108c29a2dc42d5..49d3b01707633e8c37d2bd53567fd54567035a3a 100644 --- a/shell/platform/android/io/flutter/view/FlutterMain.java +++ b/shell/platform/android/io/flutter/view/FlutterMain.java @@ -31,6 +31,7 @@ public class FlutterMain { private static final String AOT_ISOLATE_SNAPSHOT_DATA_KEY = "isolate-snapshot-data"; private static final String AOT_ISOLATE_SNAPSHOT_INSTR_KEY = "isolate-snapshot-instr"; private static final String FLX_KEY = "flx"; + private static final String SNAPSHOT_BLOB_KEY = "snapshot-blob"; private static final String FLUTTER_ASSETS_DIR_KEY = "flutter-assets-dir"; // XML Attribute keys supported in AndroidManifest.xml @@ -46,6 +47,8 @@ public class FlutterMain { FlutterMain.class.getName() + '.' + AOT_ISOLATE_SNAPSHOT_INSTR_KEY; public static final String PUBLIC_FLX_KEY = FlutterMain.class.getName() + '.' + FLX_KEY; + public static final String PUBLIC_SNAPSHOT_BLOB_KEY = + FlutterMain.class.getName() + '.' + SNAPSHOT_BLOB_KEY; public static final String PUBLIC_FLUTTER_ASSETS_DIR_KEY = FlutterMain.class.getName() + '.' + FLUTTER_ASSETS_DIR_KEY; @@ -56,7 +59,9 @@ public class FlutterMain { private static final String DEFAULT_AOT_ISOLATE_SNAPSHOT_DATA = "isolate_snapshot_data"; private static final String DEFAULT_AOT_ISOLATE_SNAPSHOT_INSTR = "isolate_snapshot_instr"; private static final String DEFAULT_FLX = "app.flx"; + private static final String DEFAULT_SNAPSHOT_BLOB = "snapshot_blob.bin"; private static final String DEFAULT_KERNEL_BLOB = "kernel_blob.bin"; + private static final String DEFAULT_PLATFORM_DILL = "platform_strong.dill"; private static final String DEFAULT_FLUTTER_ASSETS_DIR = "flutter_assets"; // Assets that are shared among all Flutter apps within an APK. @@ -74,6 +79,7 @@ public class FlutterMain { private static String sAotIsolateSnapshotData = DEFAULT_AOT_ISOLATE_SNAPSHOT_DATA; private static String sAotIsolateSnapshotInstr = DEFAULT_AOT_ISOLATE_SNAPSHOT_INSTR; private static String sFlx = DEFAULT_FLX; + private static String sSnapshotBlob = DEFAULT_SNAPSHOT_BLOB; private static String sFlutterAssetsDir = DEFAULT_FLUTTER_ASSETS_DIR; private static boolean sInitialized = false; @@ -242,6 +248,7 @@ public class FlutterMain { sAotIsolateSnapshotData = metadata.getString(PUBLIC_AOT_ISOLATE_SNAPSHOT_DATA_KEY, DEFAULT_AOT_ISOLATE_SNAPSHOT_DATA); sAotIsolateSnapshotInstr = metadata.getString(PUBLIC_AOT_ISOLATE_SNAPSHOT_INSTR_KEY, DEFAULT_AOT_ISOLATE_SNAPSHOT_INSTR); sFlx = metadata.getString(PUBLIC_FLX_KEY, DEFAULT_FLX); + sSnapshotBlob = metadata.getString(PUBLIC_SNAPSHOT_BLOB_KEY, DEFAULT_SNAPSHOT_BLOB); sFlutterAssetsDir = metadata.getString(PUBLIC_FLUTTER_ASSETS_DIR_KEY, DEFAULT_FLUTTER_ASSETS_DIR); } } catch (PackageManager.NameNotFoundException e) { @@ -261,11 +268,13 @@ public class FlutterMain { sResourceExtractor .addResource(fromFlutterAssets(sFlx)) + .addResource(fromFlutterAssets(sSnapshotBlob)) .addResource(fromFlutterAssets(sAotVmSnapshotData)) .addResource(fromFlutterAssets(sAotVmSnapshotInstr)) .addResource(fromFlutterAssets(sAotIsolateSnapshotData)) .addResource(fromFlutterAssets(sAotIsolateSnapshotInstr)) - .addResource(fromFlutterAssets(DEFAULT_KERNEL_BLOB)); + .addResource(fromFlutterAssets(DEFAULT_KERNEL_BLOB)) + .addResource(fromFlutterAssets(DEFAULT_PLATFORM_DILL)); if (sIsPrecompiledAsSharedLibrary) { sResourceExtractor .addResource(sAotSharedLibraryPath); @@ -274,7 +283,8 @@ public class FlutterMain { .addResource(sAotVmSnapshotData) .addResource(sAotVmSnapshotInstr) .addResource(sAotIsolateSnapshotData) - .addResource(sAotIsolateSnapshotInstr); + .addResource(sAotIsolateSnapshotInstr) + .addResource(sSnapshotBlob); } sResourceExtractor.start(); } diff --git a/shell/platform/android/platform_view_android_jni.cc b/shell/platform/android/platform_view_android_jni.cc index d93f9357144a6ddc4a314c3546389c12ef36aef3..6dd4b9ab3350aa540a15f4495b8f28f02a814f11 100644 --- a/shell/platform/android/platform_view_android_jni.cc +++ b/shell/platform/android/platform_view_android_jni.cc @@ -217,10 +217,10 @@ std::unique_ptr CreateIsolateConfiguration( return IsolateConfiguration::CreateForKernelList(std::move(kernels)); } if (blob) { - return IsolateConfiguration::CreateForKernel(std::move(blob)); + return IsolateConfiguration::CreateForSnapshot(std::move(blob)); } if (delta) { - return IsolateConfiguration::CreateForKernel(std::move(delta)); + return IsolateConfiguration::CreateForSnapshot(std::move(delta)); } return nullptr; }; @@ -228,6 +228,9 @@ std::unique_ptr CreateIsolateConfiguration( if (auto kernel = configuration_from_blob("kernel_blob.bin")) { return kernel; } + if (auto script = configuration_from_blob("snapshot_blob.bin")) { + return script; + } // This happens when starting isolate directly from CoreJIT snapshot. return IsolateConfiguration::CreateForAppSnapshot(); diff --git a/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm b/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm index f5d5d80dfe41a09c98df1ce8543434565cc63e16..64eb73650dcc1d1d9e135992e7f8b30cc9dbe504 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm @@ -15,6 +15,8 @@ #include "flutter/shell/platform/darwin/common/command_line.h" #include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h" +static const char* kScriptSnapshotFileName = "snapshot_blob.bin"; +static const char* kVMKernelSnapshotFileName = "platform_strong.dill"; static const char* kApplicationKernelSnapshotFileName = "kernel_blob.bin"; static blink::Settings DefaultSettingsForProcess(NSBundle* bundle = nil) { @@ -81,8 +83,8 @@ static blink::Settings DefaultSettingsForProcess(NSBundle* bundle = nil) { // In case the application bundle is still not specified, look for the App.framework in the // Frameworks directory. if (settings.application_library_path.size() == 0) { - NSString* applicationFrameworkPath = [mainBundle pathForResource:@"Frameworks/App.framework" - ofType:@""]; + NSString* applicationFrameworkPath = + [mainBundle pathForResource:@"Frameworks/App.framework" ofType:@""]; if (applicationFrameworkPath.length > 0) { NSString* executablePath = [NSBundle bundleWithPath:applicationFrameworkPath].executablePath; @@ -104,6 +106,25 @@ static blink::Settings DefaultSettingsForProcess(NSBundle* bundle = nil) { if (!blink::DartVM::IsRunningPrecompiledCode()) { // Looking for the various script and kernel snapshot buffers only makes sense if we have a // VM that can use these buffers. + { + // Check if there is a script snapshot in the assets directory we could potentially use. + NSURL* scriptSnapshotURL = [NSURL URLWithString:@(kScriptSnapshotFileName) + relativeToURL:[NSURL fileURLWithPath:assetsPath]]; + if ([[NSFileManager defaultManager] fileExistsAtPath:scriptSnapshotURL.path]) { + settings.script_snapshot_path = scriptSnapshotURL.path.UTF8String; + } + } + + { + // Check if there is a VM kernel snapshot in the assets directory we could potentially + // use. + NSURL* vmKernelSnapshotURL = [NSURL URLWithString:@(kVMKernelSnapshotFileName) + relativeToURL:[NSURL fileURLWithPath:assetsPath]]; + if ([[NSFileManager defaultManager] fileExistsAtPath:vmKernelSnapshotURL.path]) { + settings.platform_kernel_path = vmKernelSnapshotURL.path.UTF8String; + } + } + { // Check if there is an application kernel snapshot in the assets directory we could // potentially use. @@ -175,6 +196,12 @@ static blink::Settings DefaultSettingsForProcess(NSBundle* bundle = nil) { if (flutterAssetsURL != nil && [[NSFileManager defaultManager] fileExistsAtPath:flutterAssetsURL.path]) { _settings.assets_path = flutterAssetsURL.path.UTF8String; + + NSURL* scriptSnapshotPath = + [NSURL URLWithString:@(kScriptSnapshotFileName) relativeToURL:flutterAssetsURL]; + if ([[NSFileManager defaultManager] fileExistsAtPath:scriptSnapshotPath.path]) { + _settings.script_snapshot_path = scriptSnapshotPath.path.UTF8String; + } } } diff --git a/shell/platform/embedder/embedder.cc b/shell/platform/embedder/embedder.cc index c4df169639aec720ccf7d1e83cf1de75a15955d9..bd685a86b6876169596a4994da3685cfa5dfd620 100644 --- a/shell/platform/embedder/embedder.cc +++ b/shell/platform/embedder/embedder.cc @@ -268,11 +268,16 @@ FlutterResult FlutterEngineRun(size_t version, // Check whether the assets path contains Dart 2 kernel assets. const std::string kApplicationKernelSnapshotFileName = "kernel_blob.bin"; + std::string platform_kernel_path = + fml::paths::JoinPaths({settings.assets_path, "platform_strong.dill"}); std::string application_kernel_path = fml::paths::JoinPaths( {settings.assets_path, kApplicationKernelSnapshotFileName}); if (fml::IsFile(application_kernel_path)) { // Run from a kernel snapshot. - settings.application_kernel_asset = kApplicationKernelSnapshotFileName; + settings.platform_kernel_path = platform_kernel_path; + if (fml::IsFile(platform_kernel_path)) { + settings.application_kernel_asset = kApplicationKernelSnapshotFileName; + } } else { // Run from a main Dart file. settings.main_dart_file_path = args->main_path; diff --git a/shell/testing/tester_main.cc b/shell/testing/tester_main.cc index 4e10dab16f25cdbe1159f939aedd28de0d79b2ac..274ef7bb64a6c8c82fa3d656b16cec3d8152d156 100644 --- a/shell/testing/tester_main.cc +++ b/shell/testing/tester_main.cc @@ -133,7 +133,11 @@ int RunTester(const blink::Settings& settings, bool run_forever) { fml::paths::AbsolutePath(settings.main_dart_file_path), false); auto isolate_configuration = - IsolateConfiguration::CreateForKernel(std::move(main_dart_file_mapping)); + blink::DartVM::IsKernelMapping(main_dart_file_mapping.get()) + ? IsolateConfiguration::CreateForSnapshot( + std::move(main_dart_file_mapping)) + : IsolateConfiguration::CreateForSource(settings.main_dart_file_path, + settings.packages_file_path); if (!isolate_configuration) { FML_LOG(ERROR) << "Could create isolate configuration."; @@ -238,6 +242,9 @@ int main(int argc, char* argv[]) { settings.icu_data_path = "icudtl.dat"; + settings.platform_kernel_path = + fml::paths::JoinPaths({settings.assets_path, "platform_strong.dill"}); + // The tools that read logs get confused if there is a log tag specified. settings.log_tag = "";