diff --git a/engine/src/flutter/lib/snapshot/BUILD.gn b/engine/src/flutter/lib/snapshot/BUILD.gn index 5ad5fd40392..9d97333c3cf 100644 --- a/engine/src/flutter/lib/snapshot/BUILD.gn +++ b/engine/src/flutter/lib/snapshot/BUILD.gn @@ -364,6 +364,11 @@ generate_vm_patched_sdk("flutter_patched_sdk") { processed_gypis.math_runtime_sources, "//dart/runtime/lib", ], + [ + "mirrors", + processed_gypis.mirrors_runtime_sources, + "//dart/runtime/lib", + ], [ "typed_data", processed_gypis.typed_data_runtime_sources, diff --git a/engine/src/flutter/runtime/dart_controller.cc b/engine/src/flutter/runtime/dart_controller.cc index 6fbc0e37ddc..1f298ca5eac 100644 --- a/engine/src/flutter/runtime/dart_controller.cc +++ b/engine/src/flutter/runtime/dart_controller.cc @@ -44,7 +44,8 @@ std::string ResolvePath(std::string path) { } // namespace -DartController::DartController() : ui_dart_state_(nullptr) {} +DartController::DartController() : ui_dart_state_(nullptr), + kernel_bytes(nullptr), platform_kernel_bytes(nullptr) {} DartController::~DartController() { if (ui_dart_state_) { @@ -55,6 +56,12 @@ DartController::~DartController() { Dart_ShutdownIsolate(); // deletes ui_dart_state_ ui_dart_state_ = nullptr; } + if (kernel_bytes) { + free(kernel_bytes); + } + if (platform_kernel_bytes) { + free(platform_kernel_bytes); + } } bool DartController::SendStartMessage(Dart_Handle root_library) { @@ -94,10 +101,25 @@ bool DartController::SendStartMessage(Dart_Handle root_library) { return LogIfError(result); } +static void CopyVectorBytes(const std::vector& vector, + uint8_t*& bytes) { + if (bytes) { + free(bytes); + } + bytes = (uint8_t*) malloc(vector.size()); + memcpy(bytes, vector.data(), vector.size()); +} + tonic::DartErrorHandleType DartController::RunFromKernel( - const uint8_t* buffer, size_t size) { + const std::vector& kernel) { tonic::DartState::Scope scope(dart_state()); - Dart_Handle result = Dart_LoadKernel(Dart_ReadKernelBinary(buffer, size)); + // Copy kernel bytes so they won't go away after we exit this method. + // This is needed because original kernel data has to be available + // during code execution. + CopyVectorBytes(kernel, kernel_bytes); + + Dart_Handle result = Dart_LoadKernel( + Dart_ReadKernelBinary(kernel_bytes, kernel.size())); LogIfError(result); tonic::DartErrorHandleType error = tonic::GetErrorHandleType(result); if (SendStartMessage(Dart_RootLibrary())) { @@ -146,11 +168,28 @@ tonic::DartErrorHandleType DartController::RunFromSource( void DartController::CreateIsolateFor(const std::string& script_uri, const uint8_t* isolate_snapshot_data, const uint8_t* isolate_snapshot_instr, + const std::vector& platform_kernel, std::unique_ptr state) { char* error = nullptr; - Dart_Isolate isolate = Dart_CreateIsolate( - script_uri.c_str(), "main", isolate_snapshot_data, isolate_snapshot_instr, - nullptr, static_cast(state.get()), &error); + + Dart_Isolate isolate; + if (!platform_kernel.empty()) { + // Copy kernel bytes so they won't go away after we exit this method. + // This is needed because original kernel data has to be available + // during code execution. + CopyVectorBytes(platform_kernel, platform_kernel_bytes); + + isolate = Dart_CreateIsolateFromKernel( + script_uri.c_str(), "main", + Dart_ReadKernelBinary(platform_kernel_bytes, platform_kernel.size()), + nullptr /* flags */, + static_cast(state.get()), &error); + } else { + isolate = Dart_CreateIsolate( + script_uri.c_str(), "main", isolate_snapshot_data, + isolate_snapshot_instr, nullptr, + static_cast(state.get()), &error); + } FTL_CHECK(isolate) << error; ui_dart_state_ = state.release(); dart_state()->message_handler().Initialize(blink::Threads::UI()); diff --git a/engine/src/flutter/runtime/dart_controller.h b/engine/src/flutter/runtime/dart_controller.h index 0d1e6ffd322..59849974782 100644 --- a/engine/src/flutter/runtime/dart_controller.h +++ b/engine/src/flutter/runtime/dart_controller.h @@ -6,6 +6,7 @@ #define FLUTTER_RUNTIME_DART_CONTROLLER_H_ #include +#include #include "dart/runtime/include/dart_api.h" #include "lib/ftl/macros.h" @@ -19,7 +20,7 @@ class DartController { DartController(); ~DartController(); - tonic::DartErrorHandleType RunFromKernel(const uint8_t* buffer, size_t size); + tonic::DartErrorHandleType RunFromKernel(const std::vector& kernel); tonic::DartErrorHandleType RunFromPrecompiledSnapshot(); tonic::DartErrorHandleType RunFromScriptSnapshot(const uint8_t* buffer, size_t size); @@ -29,6 +30,7 @@ class DartController { void CreateIsolateFor(const std::string& script_uri, const uint8_t* isolate_snapshot_data, const uint8_t* isolate_snapshot_instr, + const std::vector& platform_kernel, std::unique_ptr ui_dart_state); UIDartState* dart_state() const { return ui_dart_state_; } @@ -40,6 +42,15 @@ class DartController { // during isolate shutdown. UIDartState* ui_dart_state_; + // Kernel binary image of dart script. This is copied and maintained + // for dart script lifespan, so that kernel loading mechanism can + // incrementally build the dart objects from it. + uint8_t* kernel_bytes; + // Kernel binary image of platform core libraries. This is copied and + // maintained for dart script lifespan, so that kernel loading mechanism can + // incrementally build the dart objects from it. + uint8_t* platform_kernel_bytes; + FTL_DISALLOW_COPY_AND_ASSIGN(DartController); }; } diff --git a/engine/src/flutter/runtime/dart_init.cc b/engine/src/flutter/runtime/dart_init.cc index 2659748235e..a9fd73e8a4a 100644 --- a/engine/src/flutter/runtime/dart_init.cc +++ b/engine/src/flutter/runtime/dart_init.cc @@ -67,6 +67,7 @@ namespace blink { const char kKernelAssetKey[] = "kernel_blob.bin"; const char kSnapshotAssetKey[] = "snapshot_blob.bin"; +const char kPlatformKernelAssetKey[] = "platform.dill"; namespace { @@ -243,6 +244,7 @@ Dart_Isolate IsolateCreateCallback(const char* script_uri, // Are we running from a Dart source file? const bool running_from_source = StringEndsWith(entry_uri, ".dart"); + void* kernel_platform = nullptr; std::vector kernel_data; std::vector snapshot_data; std::string entry_path; @@ -262,15 +264,25 @@ Dart_Isolate IsolateCreateCallback(const char* script_uri, GetUnzipperProviderForPath(std::move(bundle_path))); zip_asset_store->GetAsBuffer(kKernelAssetKey, &kernel_data); zip_asset_store->GetAsBuffer(kSnapshotAssetKey, &snapshot_data); + + std::vector platform_data; + zip_asset_store->GetAsBuffer(kPlatformKernelAssetKey, &platform_data); + if (!platform_data.empty()) { + kernel_platform = + Dart_ReadKernelBinary(platform_data.data(), platform_data.size()); + FTL_DCHECK(kernel_platform != NULL); + } } } UIDartState* parent_dart_state = static_cast(callback_data); UIDartState* dart_state = parent_dart_state->CreateForChildIsolate(); - Dart_Isolate isolate = Dart_CreateIsolate( - script_uri, main, g_default_isolate_snapshot_data, - g_default_isolate_snapshot_instructions, nullptr, dart_state, error); + Dart_Isolate isolate = kernel_platform != nullptr + ? Dart_CreateIsolateFromKernel(script_uri, main, kernel_platform, + nullptr /* flags */, dart_state, error) + : Dart_CreateIsolate(script_uri, main, g_default_isolate_snapshot_data, + g_default_isolate_snapshot_instructions, nullptr, dart_state, error); FTL_CHECK(isolate) << error; dart_state->SetIsolate(isolate); FTL_CHECK(!LogIfError( diff --git a/engine/src/flutter/runtime/dart_init.h b/engine/src/flutter/runtime/dart_init.h index 85ecaeca8e7..12496c3b999 100644 --- a/engine/src/flutter/runtime/dart_init.h +++ b/engine/src/flutter/runtime/dart_init.h @@ -20,6 +20,9 @@ extern const char kKernelAssetKey[]; // Name of the snapshot blob asset within the FLX bundle. extern const char kSnapshotAssetKey[]; +// Name of the platform kernel blob asset within the FLX bundle. +extern const char kPlatformKernelAssetKey[]; + bool IsRunningPrecompiledCode(); using EmbedderTracingCallback = ftl::Closure; diff --git a/engine/src/flutter/runtime/runtime_controller.cc b/engine/src/flutter/runtime/runtime_controller.cc index cf27b74ec11..b823f2942c8 100644 --- a/engine/src/flutter/runtime/runtime_controller.cc +++ b/engine/src/flutter/runtime/runtime_controller.cc @@ -28,12 +28,14 @@ RuntimeController::~RuntimeController() {} void RuntimeController::CreateDartController( const std::string& script_uri, const uint8_t* isolate_snapshot_data, - const uint8_t* isolate_snapshot_instr) { + const uint8_t* isolate_snapshot_instr, + const std::vector& platform_kernel) { FTL_DCHECK(!dart_controller_); dart_controller_.reset(new DartController()); dart_controller_->CreateIsolateFor( script_uri, isolate_snapshot_data, isolate_snapshot_instr, + platform_kernel, std::make_unique(this, std::make_unique(this))); UIDartState* dart_state = dart_controller_->dart_state(); diff --git a/engine/src/flutter/runtime/runtime_controller.h b/engine/src/flutter/runtime/runtime_controller.h index 6d8f9f96c96..c08fae7c2d5 100644 --- a/engine/src/flutter/runtime/runtime_controller.h +++ b/engine/src/flutter/runtime/runtime_controller.h @@ -28,7 +28,8 @@ class RuntimeController : public WindowClient, public IsolateClient { void CreateDartController(const std::string& script_uri, const uint8_t* isolate_snapshot_data, - const uint8_t* isolate_snapshot_instr); + const uint8_t* isolate_snapshot_instr, + const std::vector& kernel_platform); DartController* dart_controller() const { return dart_controller_.get(); } void SetViewportMetrics(const ViewportMetrics& metrics); diff --git a/engine/src/flutter/shell/common/engine.cc b/engine/src/flutter/shell/common/engine.cc index 9f15f33973e..4d4e08bf00e 100644 --- a/engine/src/flutter/shell/common/engine.cc +++ b/engine/src/flutter/shell/common/engine.cc @@ -181,13 +181,16 @@ void Engine::Init() { void Engine::RunBundle(const std::string& bundle_path) { TRACE_EVENT0("flutter", "Engine::RunBundle"); ConfigureAssetBundle(bundle_path); - ConfigureRuntime(GetScriptUriFromPath(bundle_path)); + std::vector platform_kernel; + GetAssetAsBuffer(blink::kPlatformKernelAssetKey, &platform_kernel); + ConfigureRuntime(GetScriptUriFromPath(bundle_path), platform_kernel); + if (blink::IsRunningPrecompiledCode()) { runtime_->dart_controller()->RunFromPrecompiledSnapshot(); } else { std::vector kernel; if (GetAssetAsBuffer(blink::kKernelAssetKey, &kernel)) { - runtime_->dart_controller()->RunFromKernel(kernel.data(), kernel.size()); + runtime_->dart_controller()->RunFromKernel(kernel); return; } std::vector snapshot; @@ -425,11 +428,13 @@ void Engine::ConfigureAssetBundle(const std::string& path) { } } -void Engine::ConfigureRuntime(const std::string& script_uri) { +void Engine::ConfigureRuntime(const std::string& script_uri, + const std::vector& platform_kernel) { runtime_ = blink::RuntimeController::Create(this); runtime_->CreateDartController(std::move(script_uri), default_isolate_snapshot_data, - default_isolate_snapshot_instr); + default_isolate_snapshot_instr, + platform_kernel); runtime_->SetViewportMetrics(viewport_metrics_); runtime_->SetLocale(language_code_, country_code_); runtime_->SetSemanticsEnabled(semantics_enabled_); diff --git a/engine/src/flutter/shell/common/engine.h b/engine/src/flutter/shell/common/engine.h index dd064867057..3e3b8efdb8b 100644 --- a/engine/src/flutter/shell/common/engine.h +++ b/engine/src/flutter/shell/common/engine.h @@ -84,7 +84,8 @@ class Engine : public blink::RuntimeDelegate { void StartAnimatorIfPossible(); void ConfigureAssetBundle(const std::string& path); - void ConfigureRuntime(const std::string& script_uri); + void ConfigureRuntime(const std::string& script_uri, + const std::vector& platform_kernel = std::vector()); bool HandleLifecyclePlatformMessage(blink::PlatformMessage* message); bool HandleNavigationPlatformMessage(