diff --git a/engine/src/flutter/common/settings.h b/engine/src/flutter/common/settings.h index 7aa561f255..7e55bf8e55 100644 --- a/engine/src/flutter/common/settings.h +++ b/engine/src/flutter/common/settings.h @@ -33,6 +33,7 @@ struct Settings { std::string application_library_path; std::string application_kernel_asset; + std::string application_kernel_list_asset; std::string main_dart_file_path; std::string packages_file_path; diff --git a/engine/src/flutter/runtime/dart_isolate.cc b/engine/src/flutter/runtime/dart_isolate.cc index 91c91f4905..22ff724e18 100644 --- a/engine/src/flutter/runtime/dart_isolate.cc +++ b/engine/src/flutter/runtime/dart_isolate.cc @@ -273,7 +273,9 @@ bool DartIsolate::PrepareForRunningFromPrecompiledCode() { return true; } -static bool LoadScriptSnapshot(std::shared_ptr mapping) { +static bool LoadScriptSnapshot(std::shared_ptr mapping, + bool last_piece) { + FXL_CHECK(last_piece) << "Script snapshots cannot be divided"; if (tonic::LogIfError(Dart_LoadScriptFromSnapshot(mapping->GetMapping(), mapping->GetSize()))) { return false; @@ -281,27 +283,40 @@ static bool LoadScriptSnapshot(std::shared_ptr mapping) { return true; } -static bool LoadKernelSnapshot(std::shared_ptr mapping) { - if (tonic::LogIfError(Dart_LoadScriptFromKernel(mapping->GetMapping(), - mapping->GetSize()))) { +static bool LoadKernelSnapshot(std::shared_ptr mapping, + bool last_piece) { + Dart_Handle library = Dart_LoadLibraryFromKernel(mapping->GetMapping(), + mapping->GetSize()); + if (tonic::LogIfError(library)) { return false; } + if (!last_piece) { + // More to come. + return true; + } + + Dart_SetRootLibrary(library); + if (tonic::LogIfError(Dart_FinalizeLoading(false))) { + return false; + } return true; } -static bool LoadSnapshot(std::shared_ptr mapping) { +static bool LoadSnapshot(std::shared_ptr mapping, + bool last_piece) { if (Dart_IsKernel(mapping->GetMapping(), mapping->GetSize())) { - return LoadKernelSnapshot(std::move(mapping)); + return LoadKernelSnapshot(std::move(mapping), last_piece); } else { - return LoadScriptSnapshot(std::move(mapping)); + return LoadScriptSnapshot(std::move(mapping), last_piece); } return false; } FXL_WARN_UNUSED_RESULT bool DartIsolate::PrepareForRunningFromSnapshot( - std::shared_ptr mapping) { + std::shared_ptr mapping, + bool last_piece) { TRACE_EVENT0("flutter", "DartIsolate::PrepareForRunningFromSnapshot"); if (phase_ != Phase::LibrariesSetup) { return false; @@ -321,10 +336,15 @@ bool DartIsolate::PrepareForRunningFromSnapshot( return false; } - if (!LoadSnapshot(mapping)) { + if (!LoadSnapshot(mapping, last_piece)) { return false; } + if (!last_piece) { + // More to come. + return true; + } + if (Dart_IsNull(Dart_RootLibrary())) { return false; } diff --git a/engine/src/flutter/runtime/dart_isolate.h b/engine/src/flutter/runtime/dart_isolate.h index 60a8dcdcd6..0999d2f6f4 100644 --- a/engine/src/flutter/runtime/dart_isolate.h +++ b/engine/src/flutter/runtime/dart_isolate.h @@ -67,7 +67,8 @@ class DartIsolate : public UIDartState { FXL_WARN_UNUSED_RESULT bool PrepareForRunningFromSnapshot( - std::shared_ptr snapshot); + std::shared_ptr snapshot, + bool last_piece = true); FXL_WARN_UNUSED_RESULT bool PrepareForRunningFromSource(const std::string& main_source_file, diff --git a/engine/src/flutter/shell/common/isolate_configuration.cc b/engine/src/flutter/shell/common/isolate_configuration.cc index 3c634022a3..eaf89b6ce3 100644 --- a/engine/src/flutter/shell/common/isolate_configuration.cc +++ b/engine/src/flutter/shell/common/isolate_configuration.cc @@ -88,6 +88,35 @@ class SourceIsolateConfiguration final : public IsolateConfiguration { FXL_DISALLOW_COPY_AND_ASSIGN(SourceIsolateConfiguration); }; +class KernelListIsolateConfiguration final : public IsolateConfiguration { + public: + KernelListIsolateConfiguration( + std::vector> kernel_pieces) + : kernel_pieces_(std::move(kernel_pieces)) {} + + // |shell::IsolateConfiguration| + bool DoPrepareIsolate(blink::DartIsolate& isolate) override { + if (blink::DartVM::IsRunningPrecompiledCode()) { + return false; + } + + for (size_t i = 0; i < kernel_pieces_.size(); i++) { + bool last_piece = i + 1 == kernel_pieces_.size(); + if (!isolate.PrepareForRunningFromSnapshot(std::move(kernel_pieces_[i]), + last_piece)) { + return false; + } + } + + return true; + } + + private: + std::vector> kernel_pieces_; + + FXL_DISALLOW_COPY_AND_ASSIGN(KernelListIsolateConfiguration); +}; + std::unique_ptr IsolateConfiguration::InferFromSettings( const blink::Settings& settings, fxl::RefPtr asset_manager) { @@ -107,6 +136,7 @@ std::unique_ptr IsolateConfiguration::InferFromSettings( // Running from kernel snapshot. { + // TODO(engine): Add AssetManager::GetAsMapping or such to avoid the copy. std::vector kernel; if (asset_manager && asset_manager->GetAsBuffer( settings.application_kernel_asset, &kernel)) { @@ -117,6 +147,7 @@ std::unique_ptr IsolateConfiguration::InferFromSettings( // Running from script snapshot. { + // TODO(engine): Add AssetManager::GetAsMapping or such to avoid the copy. std::vector script_snapshot; if (asset_manager && asset_manager->GetAsBuffer( settings.script_snapshot_path, &script_snapshot)) { @@ -125,6 +156,42 @@ std::unique_ptr IsolateConfiguration::InferFromSettings( } } + // Running from kernel divided into several pieces (for sharing). + { + // TODO(fuchsia): Add AssetManager::GetAsMapping or such to avoid the copy. + // TODO(fuchsia): Use async blobfs API once it becomes available. + std::vector kernel_list; + if (asset_manager && + asset_manager->GetAsBuffer(settings.application_kernel_list_asset, + &kernel_list)) { + std::vector> kernel_pieces; + + size_t piece_path_start = 0; + while (piece_path_start < kernel_list.size()) { + size_t piece_path_end = piece_path_start; + while ((piece_path_end < kernel_list.size()) && + (kernel_list[piece_path_end] != '\n')) { + piece_path_end++; + } + + std::string piece_path(reinterpret_cast(&kernel_list[piece_path_start]), + piece_path_end - piece_path_start); + std::vector piece; + if (!asset_manager->GetAsBuffer(piece_path, &piece)) { + FXL_LOG(ERROR) << "Failed to load: " << piece_path; + return nullptr; + } + + kernel_pieces.emplace_back( + std::make_unique(std::move(piece))); + + piece_path_start = piece_path_end + 1; + } + + return CreateForKernelList(std::move(kernel_pieces)); + } + } + return nullptr; } @@ -145,4 +212,10 @@ std::unique_ptr IsolateConfiguration::CreateForSource( std::move(packages_path)); } +std::unique_ptr IsolateConfiguration::CreateForKernelList( + std::vector> kernel_pieces) { + return std::make_unique( + std::move(kernel_pieces)); +} + } // namespace shell diff --git a/engine/src/flutter/shell/common/isolate_configuration.h b/engine/src/flutter/shell/common/isolate_configuration.h index 82d06dac62..67494407bb 100644 --- a/engine/src/flutter/shell/common/isolate_configuration.h +++ b/engine/src/flutter/shell/common/isolate_configuration.h @@ -33,6 +33,9 @@ class IsolateConfiguration { std::string main_path, std::string packages_path); + static std::unique_ptr CreateForKernelList( + std::vector> kernel_pieces); + IsolateConfiguration(); virtual ~IsolateConfiguration();