From 1084a83f115aa98bf7883ab3ef207ecd1790502c Mon Sep 17 00:00:00 2001 From: Ryan Macnak Date: Tue, 11 Apr 2017 14:53:14 -0700 Subject: [PATCH] AOT for Fuchsia. (#3570) --- BUILD.gn | 8 +- build/aot_snapshot.py | 59 +++++++ build/flutter_app.gni | 204 ++++++++++++++++++++-- build/package.py | 13 +- build/{snapshot.py => script_snapshot.py} | 0 content_handler/BUILD.gn | 158 +++++++++-------- content_handler/app.cc | 7 - content_handler/runtime_holder.cc | 89 +++++++++- content_handler/runtime_holder.h | 1 + lib/snapshot/snapshot.c.tmpl | 20 ++- lib/snapshot/snapshot.h | 14 ++ runtime/dart_controller.cc | 11 +- runtime/dart_controller.h | 5 +- runtime/dart_init.cc | 194 +++----------------- runtime/dart_init.h | 31 +--- runtime/dart_vm_entry_points_fuchsia.txt | 4 + runtime/runtime_controller.cc | 6 +- runtime/runtime_controller.h | 4 +- runtime/runtime_init.cc | 9 +- runtime/runtime_init.h | 7 +- shell/common/engine.cc | 111 +++++++++++- travis/licenses_golden/licenses_flutter | 1 + 22 files changed, 627 insertions(+), 329 deletions(-) create mode 100755 build/aot_snapshot.py rename build/{snapshot.py => script_snapshot.py} (100%) create mode 100644 lib/snapshot/snapshot.h create mode 100644 runtime/dart_vm_entry_points_fuchsia.txt diff --git a/BUILD.gn b/BUILD.gn index 8ca1c7ccc01..84ac5f072ce 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -6,25 +6,23 @@ group("flutter") { testonly = true deps = [ - "//flutter/sky", "//flutter/lib/snapshot:generate_snapshot_bin", + "//flutter/sky", ] if (is_fuchsia) { deps += [ "//flutter/content_handler", + "//flutter/content_handler:aot_content_handler", "//flutter/examples", "//flutter/flow", - "//flutter/runtime", ] } # If on the host, compile all unittests targets. if (current_toolchain == host_toolchain) { if (is_mac) { - deps += [ - "//flutter/shell/platform/darwin:flutter_channels_unittests", - ] + deps += [ "//flutter/shell/platform/darwin:flutter_channels_unittests" ] } deps += [ "//flutter/fml:fml_unittests", diff --git a/build/aot_snapshot.py b/build/aot_snapshot.py new file mode 100755 index 00000000000..4078d834a42 --- /dev/null +++ b/build/aot_snapshot.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import argparse +import subprocess +import os +import sys + + +def main(): + parser = argparse.ArgumentParser(description='Snapshot a Flutter application') + + parser.add_argument('--snapshotter-path', type=str, required=True, + help='The Flutter snapshotter') + + parser.add_argument('--main-dart', type=str, required=True, + help='The main.dart file to use') + + parser.add_argument('--url-mapping', type=str, action='append', + help='The main.dart file to use') + parser.add_argument('--entry-points-manifest', type=str, action='append', + help='The main.dart file to use') + + parser.add_argument('--packages', type=str, required=True, + help='The package map to use') + parser.add_argument('--assembly', type=str, required=True, + help='Where to output application assembly') + parser.add_argument('--depfile', type=str, required=True, + help='Where to output dependency information') + parser.add_argument('--root-build-dir', type=str, required=True, + help='The root build dir for --depfile and --snapshot') + + args = parser.parse_args() + + cmd = [ + args.snapshotter_path, + "--enable_mirrors=false", + "--await_is_keyword", + "--assert_initializer", + '--snapshot_kind=app-aot-assembly', + '--packages=%s' % args.packages, + '--assembly=%s' % args.assembly, + '--dependencies=%s' % args.depfile, + ] + for url_mapping in args.url_mapping: + cmd.append("--url_mapping=" + url_mapping) + for entry_points_manifest in args.entry_points_manifest: + cmd.append("--embedder_entry_points_manifest=" + entry_points_manifest) + cmd.append(args.main_dart) + + result = subprocess.call(cmd, cwd=args.root_build_dir) + + return result + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/build/flutter_app.gni b/build/flutter_app.gni index bd570b36093..63e1432d756 100644 --- a/build/flutter_app.gni +++ b/build/flutter_app.gni @@ -5,6 +5,9 @@ assert(is_fuchsia) import("//build/dart/dart_package.gni") +import("//flutter/lib/ui/dart_ui.gni") +import("//apps/mozart/lib/flutter/sdk_ext/sdk_ext.gni") +import("//lib/fidl/dart/sdk_ext/sdk_ext.gni") # Defines a Flutter application # @@ -58,14 +61,17 @@ template("flutter_app") { bundle_name = "${target_name}.flx" } - flutter_snapshot_label = "//dart/runtime/bin:gen_snapshot($host_toolchain)" - flutter_snapshot_dir = get_label_info(flutter_snapshot_label, "root_out_dir") - flutter_snapshot = "$flutter_snapshot_dir/gen_snapshot" + gen_snapshot_label = "//dart/runtime/bin:gen_snapshot($host_toolchain)" + gen_snapshot_dir = get_label_info(gen_snapshot_label, "root_out_dir") + gen_snapshot = "$gen_snapshot_dir/gen_snapshot" flutter_core_snapshot_label = "//flutter/lib/snapshot:generate_snapshot_bin" - flutter_core_snapshot_gen_dir = get_label_info(flutter_core_snapshot_label, "target_gen_dir") - flutter_core_snapshot_vm_data = "$flutter_core_snapshot_gen_dir/vm_isolate_snapshot.bin" - flutter_core_snapshot_isolate_data = "$flutter_core_snapshot_gen_dir/isolate_snapshot.bin" + flutter_core_snapshot_gen_dir = + get_label_info(flutter_core_snapshot_label, "target_gen_dir") + flutter_core_snapshot_vm_data = + "$flutter_core_snapshot_gen_dir/vm_isolate_snapshot.bin" + flutter_core_snapshot_isolate_data = + "$flutter_core_snapshot_gen_dir/isolate_snapshot.bin" flutter_root = "//lib/flutter" flutter_tools_label = "$flutter_root/packages/flutter_tools($host_toolchain)" @@ -80,9 +86,9 @@ template("flutter_app") { main_dart = invoker.main_dart - flutter_snapshot_name = target_name + "_snapshot" + script_snapshot_label = target_name + "_snapshot" - action(flutter_snapshot_name) { + action(script_snapshot_label) { depfile = snapshot_depfile inputs = [ @@ -97,11 +103,11 @@ template("flutter_app") { sources = invoker.sources } - script = "//flutter/build/snapshot.py" + script = "//flutter/build/script_snapshot.py" args = [ "--snapshotter-path", - rebase_path(flutter_snapshot), + rebase_path(gen_snapshot), "--vm-snapshot-data", rebase_path(flutter_core_snapshot_vm_data), "--isolate-snapshot-data", @@ -120,8 +126,8 @@ template("flutter_app") { deps = [ ":$dart_package_name", - flutter_snapshot_label, flutter_core_snapshot_label, + gen_snapshot_label, ] if (defined(invoker.deps)) { @@ -164,6 +170,8 @@ template("flutter_app") { rebase_path(root_build_dir), "--depfile", rebase_path(bundle_depfile), + "--interpreter", + "file:///system/apps/flutter_runner", ] if (defined(invoker.manifest)) { args += [ @@ -173,7 +181,179 @@ template("flutter_app") { } deps = [ - ":$flutter_snapshot_name", + ":$script_snapshot_label", + flutter_tools_label, + ] + } +} + +template("flutter_aot_app") { + assert(defined(invoker.main_dart), "Must define main_dart") + + dart_package_name = target_name + "_dart_package" + + dart_package(dart_package_name) { + forward_variables_from(invoker, + [ + "analysis_options", + "deps", + "disable_analysis", + "source_dir", + ]) + if (defined(invoker.package_name)) { + package_name = invoker.package_name + } else { + infer_package_name = true + } + } + + if (defined(invoker.output_name)) { + bundle_name = invoker.output_name + } else { + bundle_name = "${target_name}.flx" + } + + gen_snapshot_label = "//dart/runtime/bin:gen_snapshot($host_toolchain)" + gen_snapshot_dir = get_label_info(gen_snapshot_label, "root_out_dir") + gen_snapshot = "$gen_snapshot_dir/gen_snapshot" + + flutter_root = "//lib/flutter" + flutter_tools_label = "$flutter_root/packages/flutter_tools($host_toolchain)" + flutter_tools_out_dir = get_label_info(flutter_tools_label, "root_out_dir") + flutter_tools_bin = "$flutter_tools_out_dir/dart-tools/flutter_tools" + + dot_packages = "$target_gen_dir/$dart_package_name.packages" + bundle_path = "$root_out_dir/$bundle_name" + bundle_depfile = "$target_gen_dir/$bundle_name.d" + assembly_path = "$target_gen_dir/$target_name.S" + assembly_depfile = "${assembly_path}.d" + + main_dart = invoker.main_dart + + assembly_label = target_name + "_assembly" + + action(assembly_label) { + depfile = assembly_depfile + + inputs = [ main_dart ] + fidl_dart_sdk_ext_files + mozart_dart_sdk_ext_files + + outputs = [ + assembly_path, + ] + + if (defined(invoker.sources)) { + sources = invoker.sources + } + + script = "//flutter/build/aot_snapshot.py" + args = [ + "--snapshotter-path", + rebase_path(gen_snapshot), + "--assembly", + rebase_path(assembly_path, root_build_dir), + "--packages", + rebase_path(dot_packages), + "--depfile", + rebase_path(assembly_depfile), + + "--url-mapping", + "dart:ui," + rebase_path(dart_ui_path), + "--url-mapping", + "dart:fidl.internal," + rebase_path(fidl_dart_sdk_ext_lib), + "--url-mapping", + "dart:mozart.internal," + rebase_path(mozart_dart_sdk_ext_lib), + "--url-mapping", + "dart:vmservice_sky," + rebase_path( + "$root_gen_dir/dart-pkg/sky_engine/sdk_ext/vmservice_io.dart"), + + "--entry-points-manifest", + rebase_path("//flutter/runtime/dart_vm_entry_points.txt"), + "--entry-points-manifest", + rebase_path("//flutter/runtime/dart_vm_entry_points_fuchsia.txt"), + + "--main-dart", + rebase_path(main_dart), + "--root-build-dir", + rebase_path(root_build_dir), + ] + + deps = [ + ":$dart_package_name", + "//flutter/lib/snapshot:generate_dart_ui", + gen_snapshot_label, + ] + + if (defined(invoker.deps)) { + deps += invoker.deps + } + } + + dylib_label = target_name + "_dylib" + + outer_target_name = target_name + shared_library(dylib_label) { + deps = [ + ":$assembly_label", + ] + sources = [ + assembly_path, + ] + cflags = [ + "-nostdlib", + "-nostartfiles", + ] + output_name = outer_target_name + } + + dylib_path = "$root_out_dir/lib.unstripped/lib$target_name.so" + + action(target_name) { + depfile = bundle_depfile + + inputs = [ + dylib_path, + ] + if (defined(invoker.manifest)) { + inputs += [ rebase_path(invoker.manifest) ] + } + + outputs = [ + bundle_path, + ] + + script = "//flutter/build/package.py" + + args = [ + "--flutter-root", + rebase_path(flutter_root), + "--flutter-tools", + rebase_path(flutter_tools_bin), + "--working-dir", + rebase_path("$target_gen_dir/build"), + "--app-dir", + rebase_path("."), + "--packages", + rebase_path(dot_packages), + "--output-file", + rebase_path(bundle_path), + "--dylib", + rebase_path(dylib_path), + "--build-root", + rebase_path(root_build_dir), + "--depfile", + rebase_path(bundle_depfile), + "--interpreter", + "file:///system/apps/flutter_aot_runner", + ] + if (defined(invoker.manifest)) { + args += [ + "--manifest", + rebase_path(invoker.manifest), + ] + } + + deps = [ + ":$dylib_label", flutter_tools_label, ] } diff --git a/build/package.py b/build/package.py index d591da57c7a..e5d3cca477a 100755 --- a/build/package.py +++ b/build/package.py @@ -22,14 +22,18 @@ def main(): help='The root of the app') parser.add_argument('--packages', type=str, required=True, help='The package map to use') - parser.add_argument('--snapshot', type=str, required=True, + parser.add_argument('--snapshot', type=str, required=False, help='Path to application snapshot') + parser.add_argument('--dylib', type=str, required=False, + help='Path to AOT dylib') parser.add_argument('--output-file', type=str, required=True, help='Where to output application bundle') parser.add_argument('--build-root', type=str, required=True, help='The build\'s root directory') parser.add_argument('--depfile', type=str, required=True, help='Where to output application bundle dependencies') + parser.add_argument('--interpreter', type=str, required=True, + help='') parser.add_argument('--manifest', type=str, help='The application manifest') args = parser.parse_args() @@ -41,12 +45,15 @@ def main(): args.flutter_tools, '--working-dir=%s' % args.working_dir, '--packages=%s' % args.packages, - '--snapshot=%s' % args.snapshot, '--output-file=%s' % args.output_file, - '--header=#!fuchsia file:///system/apps/flutter_runner', + '--header=#!fuchsia %s' % args.interpreter, '--build-root=%s' % args.build_root, '--depfile=%s' % args.depfile, ] + if args.snapshot != None: + call_args.append('--snapshot=%s' % args.snapshot) + if args.dylib != None: + call_args.append('--dylib=%s' % args.dylib) if 'manifest' in args: call_args.append('--manifest=%s' % args.manifest) diff --git a/build/snapshot.py b/build/script_snapshot.py similarity index 100% rename from build/snapshot.py rename to build/script_snapshot.py diff --git a/content_handler/BUILD.gn b/content_handler/BUILD.gn index 472dc91abeb..0b543eadc77 100644 --- a/content_handler/BUILD.gn +++ b/content_handler/BUILD.gn @@ -9,86 +9,100 @@ declare_args() { flutter_use_vulkan_native_surface = false } -executable("content_handler") { - output_name = "flutter_runner" +template("flutter_content_handler") { + invoker_output_name = invoker.output_name + extra_deps = invoker.extra_deps - defines = [] + executable(target_name) { + output_name = invoker_output_name - libs = [] + defines = [] - sources = [ - "app.cc", - "app.h", - "application_controller_impl.cc", - "application_controller_impl.h", - "content_handler_thread.cc", - "content_handler_thread.h", - "main.cc", - "rasterizer.cc", - "rasterizer.h", - "runtime_holder.cc", - "runtime_holder.h", - "service_protocol_hooks.cc", - "service_protocol_hooks.h", - "software_rasterizer.cc", - "software_rasterizer.h", - ] + libs = [] - deps = [ - "//application/lib/app", - "//apps/icu_data/lib", - "//apps/mozart/lib/skia:vmo", - "//apps/mozart/services/buffers", - "//apps/mozart/services/buffers/cpp", - "//apps/mozart/services/composition", - "//apps/mozart/services/input", - "//apps/mozart/services/views", - "//apps/tracing/lib/trace:provider", - "//dart/runtime:dart_api", + sources = [ + "app.cc", + "app.h", + "application_controller_impl.cc", + "application_controller_impl.h", + "content_handler_thread.cc", + "content_handler_thread.h", + "main.cc", + "rasterizer.cc", + "rasterizer.h", + "runtime_holder.cc", + "runtime_holder.h", + "service_protocol_hooks.cc", + "service_protocol_hooks.h", + "software_rasterizer.cc", + "software_rasterizer.h", + ] - "//dart/runtime:libdart_jit", - # TODO(abarth): We shouldn't need to depend on libdart_builtin but we fail - # to link otherwise. - "//dart/runtime/bin:libdart_builtin", - "//dart/runtime/vm:libdart_platform", - "//flutter/assets", - "//flutter/common", - "//flutter/flow", - "//flutter/glue", - "//flutter/lib/ui", - "//flutter/runtime", - "//flutter/sky/engine/platform", - "//lib/fidl/dart/sdk_ext", - "//lib/ftl", - "//lib/mtl", - "//lib/tonic/mx", - "//lib/zip", - "//third_party/rapidjson", - "//third_party/skia", - ] + deps = [ + "//application/lib/app", + "//apps/icu_data/lib", + "//apps/mozart/lib/skia:vmo", + "//apps/mozart/services/buffers", + "//apps/mozart/services/buffers/cpp", + "//apps/mozart/services/composition", + "//apps/mozart/services/input", + "//apps/mozart/services/views", + "//apps/tracing/lib/trace:provider", - if (flutter_enable_vulkan) { - defines += [ "FLUTTER_ENABLE_VULKAN=1" ] + # TODO(abarth): We shouldn't need to depend on libdart_builtin but we fail + # to link otherwise. + "//dart/runtime/bin:libdart_builtin", + "//dart/runtime/vm:libdart_platform", + "//flutter/assets", + "//flutter/common", + "//flutter/flow", + "//flutter/glue", + "//flutter/lib/ui", + "//flutter/runtime", + "//flutter/sky/engine/platform", + "//lib/fidl/dart/sdk_ext", + "//lib/ftl", + "//lib/mtl", + "//lib/tonic/mx", + "//lib/zip", + "//third_party/rapidjson", + "//third_party/skia", + ] + deps += extra_deps - if (flutter_use_vulkan_native_surface) { - defines += [ "FLUTTER_USE_VULKAN_NATIVE_SURFACE=1" ] - sources += [ - "direct_input.cc", - "direct_input.h", - "vulkan_native_rasterizer.cc", - "vulkan_native_rasterizer.h", - ] - libs += [ "hid" ] - } else { - sources += [ - "vulkan_rasterizer.cc", - "vulkan_rasterizer.h", + if (flutter_enable_vulkan) { + defines += [ "FLUTTER_ENABLE_VULKAN=1" ] + + if (flutter_use_vulkan_native_surface) { + defines += [ "FLUTTER_USE_VULKAN_NATIVE_SURFACE=1" ] + sources += [ + "direct_input.cc", + "direct_input.h", + "vulkan_native_rasterizer.cc", + "vulkan_native_rasterizer.h", + ] + libs += [ "hid" ] + } else { + sources += [ + "vulkan_rasterizer.cc", + "vulkan_rasterizer.h", + ] + } + + deps += [ + "//flutter/vulkan", + "//magma:vulkan", ] } - - deps += [ - "//flutter/vulkan", - "//magma:vulkan", - ] } } + +flutter_content_handler("content_handler") { + output_name = "flutter_runner" + extra_deps = [ "//dart/runtime:libdart_jit" ] +} + +flutter_content_handler("aot_content_handler") { + output_name = "flutter_aot_runner" + extra_deps = [ "//dart/runtime:libdart_precompiled_runtime" ] +} diff --git a/content_handler/app.cc b/content_handler/app.cc index df44589e963..58b9a14b997 100644 --- a/content_handler/app.cc +++ b/content_handler/app.cc @@ -11,9 +11,6 @@ #include "apps/tracing/lib/trace/provider.h" #include "flutter/common/settings.h" #include "flutter/common/threads.h" -#include "flutter/content_handler/service_protocol_hooks.h" -#include "flutter/runtime/dart_init.h" -#include "flutter/runtime/runtime_init.h" #include "flutter/sky/engine/platform/fonts/fuchsia/FontCacheFuchsia.h" #include "lib/ftl/macros.h" #include "lib/ftl/tasks/task_runner.h" @@ -60,10 +57,6 @@ App::App() { blink::Settings settings; settings.enable_observatory = true; blink::Settings::Set(settings); - blink::InitRuntime(); - - blink::SetRegisterNativeServiceProtocolExtensionHook( - ServiceProtocolHooks::RegisterHooks); blink::SetFontProvider( context_->ConnectToEnvironmentService()); diff --git a/content_handler/runtime_holder.cc b/content_handler/runtime_holder.cc index 052869a01d8..7da9a54d87b 100644 --- a/content_handler/runtime_holder.cc +++ b/content_handler/runtime_holder.cc @@ -4,6 +4,8 @@ #include "flutter/content_handler/runtime_holder.h" +#include +#include #include #include "application/lib/app/connect.h" @@ -11,13 +13,18 @@ #include "flutter/assets/zip_asset_store.h" #include "flutter/common/threads.h" #include "flutter/content_handler/rasterizer.h" +#include "flutter/content_handler/service_protocol_hooks.h" +#include "flutter/lib/snapshot/snapshot.h" #include "flutter/lib/ui/window/pointer_data_packet.h" #include "flutter/runtime/asset_font_selector.h" #include "flutter/runtime/dart_controller.h" +#include "flutter/runtime/dart_init.h" +#include "flutter/runtime/runtime_init.h" #include "lib/fidl/dart/sdk_ext/src/natives.h" #include "lib/ftl/functional/make_copyable.h" #include "lib/ftl/logging.h" #include "lib/ftl/time/time_delta.h" +#include "lib/mtl/vmo/vector.h" #include "lib/tonic/mx/mx_converter.h" #include "lib/zip/create_unzipper.h" #include "third_party/rapidjson/rapidjson/document.h" @@ -32,6 +39,7 @@ namespace { constexpr char kKernelKey[] = "kernel_blob.bin"; constexpr char kSnapshotKey[] = "snapshot_blob.bin"; +constexpr char kDylibKey[] = "libapp.so"; constexpr char kAssetChannel[] = "flutter/assets"; // Maximum number of frames in flight. @@ -103,6 +111,57 @@ void RuntimeHolder::Init( outgoing_services_ = std::move(outgoing_services); InitRootBundle(std::move(bundle)); + + const uint8_t* vm_snapshot_data; + const uint8_t* vm_snapshot_instr; + const uint8_t* default_isolate_snapshot_data; + const uint8_t* default_isolate_snapshot_instr; + if (!Dart_IsPrecompiledRuntime()) { + vm_snapshot_data = ::kDartVmSnapshotData; + vm_snapshot_instr = ::kDartVmSnapshotInstructions; + default_isolate_snapshot_data = ::kDartIsolateCoreSnapshotData; + default_isolate_snapshot_instr = ::kDartIsolateCoreSnapshotInstructions; + } else { + std::vector dylib_blob; + if (!asset_store_->GetAsBuffer(kDylibKey, &dylib_blob)) { + FTL_LOG(ERROR) << "Failed to extract app dylib"; + return; + } + + mx::vmo dylib_vmo; + if (!mtl::VmoFromVector(dylib_blob, &dylib_vmo)) { + FTL_LOG(ERROR) << "Failed to load app dylib"; + return; + } + + dlerror(); + dylib_handle_ = dlopen_vmo(dylib_vmo.get(), RTLD_LAZY); + if (dylib_handle_ == nullptr) { + FTL_LOG(ERROR) << "dlopen failed: " << dlerror(); + return; + } + vm_snapshot_data = reinterpret_cast( + dlsym(dylib_handle_, "_kDartVmSnapshotData")); + vm_snapshot_instr = reinterpret_cast( + dlsym(dylib_handle_, "_kDartVmSnapshotInstructions")); + default_isolate_snapshot_data = reinterpret_cast( + dlsym(dylib_handle_, "_kDartIsolateSnapshotData")); + default_isolate_snapshot_instr = reinterpret_cast( + dlsym(dylib_handle_, "_kDartIsolateSnapshotInstructions")); + } + + // TODO(rmacnak): We should generate the AOT vm snapshot separately from + // each app so we can initialize before receiving the first app bundle. + static bool first_app = true; + if (first_app) { + first_app = false; + blink::InitRuntime(vm_snapshot_data, vm_snapshot_instr, + default_isolate_snapshot_data, + default_isolate_snapshot_instr); + + blink::SetRegisterNativeServiceProtocolExtensionHook( + ServiceProtocolHooks::RegisterHooks); + } } void RuntimeHolder::CreateView( @@ -118,8 +177,9 @@ void RuntimeHolder::CreateView( std::vector kernel; std::vector snapshot; - if (!asset_store_->GetAsBuffer(kKernelKey, &kernel)) { - if (!asset_store_->GetAsBuffer(kSnapshotKey, &snapshot)) { + if (!Dart_IsPrecompiledRuntime()) { + if (!asset_store_->GetAsBuffer(kKernelKey, &kernel) && + !asset_store_->GetAsBuffer(kSnapshotKey, &snapshot)) { FTL_LOG(ERROR) << "Unable to load kernel or snapshot from root bundle."; return; } @@ -156,16 +216,33 @@ void RuntimeHolder::CreateView( ]() mutable { rasterizer->SetScene(std::move(scene)); })); runtime_ = blink::RuntimeController::Create(this); - runtime_->CreateDartController(script_uri); + + const uint8_t* isolate_snapshot_data; + const uint8_t* isolate_snapshot_instr; + if (!Dart_IsPrecompiledRuntime()) { + isolate_snapshot_data = ::kDartIsolateCoreSnapshotData; + isolate_snapshot_instr = ::kDartIsolateCoreSnapshotInstructions; + } else { + isolate_snapshot_data = reinterpret_cast( + dlsym(dylib_handle_, "_kDartIsolateSnapshotData")); + isolate_snapshot_instr = reinterpret_cast( + dlsym(dylib_handle_, "_kDartIsolateSnapshotInstructions")); + } + runtime_->CreateDartController(script_uri, isolate_snapshot_data, + isolate_snapshot_instr); + runtime_->SetViewportMetrics(viewport_metrics_); #if FLUTTER_ENABLE_VULKAN && FLUTTER_USE_VULKAN_NATIVE_SURFACE direct_input_->SetViewportMetrics(viewport_metrics_); #endif // FLUTTER_ENABLE_VULKAN && FLUTTER_USE_VULKAN_NATIVE_SURFACE - if (!kernel.empty()) { + + if (Dart_IsPrecompiledRuntime()) { + runtime_->dart_controller()->RunFromPrecompiledSnapshot(); + } else if (!kernel.empty()) { runtime_->dart_controller()->RunFromKernel(kernel.data(), kernel.size()); } else { - runtime_->dart_controller()->RunFromSnapshot(snapshot.data(), - snapshot.size()); + runtime_->dart_controller()->RunFromScriptSnapshot(snapshot.data(), + snapshot.size()); } } diff --git a/content_handler/runtime_holder.h b/content_handler/runtime_holder.h index 628f8501ffb..748830cc608 100644 --- a/content_handler/runtime_holder.h +++ b/content_handler/runtime_holder.h @@ -84,6 +84,7 @@ class RuntimeHolder : public blink::RuntimeDelegate, std::vector root_bundle_data_; ftl::RefPtr asset_store_; + void* dylib_handle_ = nullptr; std::unique_ptr rasterizer_; std::unique_ptr runtime_; diff --git a/lib/snapshot/snapshot.c.tmpl b/lib/snapshot/snapshot.c.tmpl index 52ed833d1ba..7b0fdba6203 100644 --- a/lib/snapshot/snapshot.c.tmpl +++ b/lib/snapshot/snapshot.c.tmpl @@ -10,16 +10,20 @@ // generated snapshot binary file for the vm isolate. // This string forms the content of the dart vm isolate snapshot which // is loaded into the vm isolate. -const uint8_t kDartVmSnapshotData[] - __attribute__((visibility("default"), aligned(8), used)) = { %s }; -const uint8_t kDartVmSnapshotInstructions[] - __attribute__((visibility("default"), aligned(8), used)) = {}; +const uint8_t kDartVmSnapshotData_[] + __attribute__((aligned(8))) = { %s }; +const uint8_t* kDartVmSnapshotData + __attribute__((visibility("default"), used)) = kDartVmSnapshotData_; +const uint8_t* kDartVmSnapshotInstructions + __attribute__((visibility("default"), used)) = NULL; // The string on the next line will be filled in with the contents of the // generated snapshot binary file for a regular dart isolate. // This string forms the content of a regular dart isolate snapshot which // is loaded into an isolate when it is created. -const uint8_t kDartIsolateSnapshotData[] - __attribute__((visibility("default"), aligned(8), used)) = { %s }; -const uint8_t kDartIsolateSnapshotInstructions[] - __attribute__((visibility("default"), aligned(8), used)) = {}; +const uint8_t kDartIsolateCoreSnapshotData_[] + __attribute__((aligned(8))) = { %s }; +const uint8_t* kDartIsolateCoreSnapshotData + __attribute__((visibility("default"), used)) = kDartIsolateCoreSnapshotData_; +const uint8_t* kDartIsolateCoreSnapshotInstructions + __attribute__((visibility("default"), used)) = NULL; diff --git a/lib/snapshot/snapshot.h b/lib/snapshot/snapshot.h new file mode 100644 index 00000000000..f6ef1300e30 --- /dev/null +++ b/lib/snapshot/snapshot.h @@ -0,0 +1,14 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include +#include +#include + +extern "C" { +extern const uint8_t* kDartVmSnapshotData; +extern const uint8_t* kDartVmSnapshotInstructions; +extern const uint8_t* kDartIsolateCoreSnapshotData; +extern const uint8_t* kDartIsolateCoreSnapshotInstructions; +} diff --git a/runtime/dart_controller.cc b/runtime/dart_controller.cc index 90ce11459c5..aebc258532c 100644 --- a/runtime/dart_controller.cc +++ b/runtime/dart_controller.cc @@ -123,7 +123,7 @@ tonic::DartErrorHandleType DartController::RunFromPrecompiledSnapshot() { return tonic::kNoError; } -tonic::DartErrorHandleType DartController::RunFromSnapshot( +tonic::DartErrorHandleType DartController::RunFromScriptSnapshot( const uint8_t* buffer, size_t size) { tonic::DartState::Scope scope(dart_state()); Dart_Handle result = Dart_LoadScriptFromSnapshot(buffer, size); @@ -151,14 +151,13 @@ tonic::DartErrorHandleType DartController::RunFromSource( } void DartController::CreateIsolateFor(const std::string& script_uri, + const uint8_t* isolate_snapshot_data, + const uint8_t* isolate_snapshot_instr, std::unique_ptr state) { char* error = nullptr; Dart_Isolate isolate = Dart_CreateIsolate( - script_uri.c_str(), "main", - reinterpret_cast(DART_SYMBOL(kDartIsolateSnapshotData)), - reinterpret_cast(DART_SYMBOL(kDartIsolateSnapshotInstructions)), - nullptr, - static_cast(state.get()), &error); + 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/runtime/dart_controller.h b/runtime/dart_controller.h index 0c9c9048ff6..0d1e6ffd322 100644 --- a/runtime/dart_controller.h +++ b/runtime/dart_controller.h @@ -21,11 +21,14 @@ class DartController { tonic::DartErrorHandleType RunFromKernel(const uint8_t* buffer, size_t size); tonic::DartErrorHandleType RunFromPrecompiledSnapshot(); - tonic::DartErrorHandleType RunFromSnapshot(const uint8_t* buffer, size_t size); + tonic::DartErrorHandleType RunFromScriptSnapshot(const uint8_t* buffer, + size_t size); tonic::DartErrorHandleType RunFromSource(const std::string& main, const std::string& packages); void CreateIsolateFor(const std::string& script_uri, + const uint8_t* isolate_snapshot_data, + const uint8_t* isolate_snapshot_instr, std::unique_ptr ui_dart_state); UIDartState* dart_state() const { return ui_dart_state_; } diff --git a/runtime/dart_init.cc b/runtime/dart_init.cc index d3c1f14ebe9..abbb113cf9e 100644 --- a/runtime/dart_init.cc +++ b/runtime/dart_init.cc @@ -4,10 +4,7 @@ #include "flutter/runtime/dart_init.h" -#include -#include #include -#include #include #include #include @@ -31,8 +28,6 @@ #include "flutter/runtime/start_up.h" #include "lib/ftl/arraysize.h" #include "lib/ftl/build_config.h" -#include "lib/ftl/files/eintr_wrapper.h" -#include "lib/ftl/files/unique_fd.h" #include "lib/ftl/logging.h" #include "lib/ftl/time/time_delta.h" #include "lib/tonic/converter/dart_converter.h" @@ -115,9 +110,11 @@ static const char* kDartEndlessTraceBufferArgs[]{ constexpr char kFileUriPrefix[] = "file://"; constexpr size_t kFileUriPrefixLength = sizeof(kFileUriPrefix) - 1; -bool g_service_isolate_initialized = false; -ServiceIsolateHook g_service_isolate_hook = nullptr; -RegisterNativeServiceProtocolExtensionHook +static const uint8_t* g_default_isolate_snapshot_data = nullptr; +static const uint8_t* g_default_isolate_snapshot_instructions = nullptr; +static bool g_service_isolate_initialized = false; +static ServiceIsolateHook g_service_isolate_hook = nullptr; +static RegisterNativeServiceProtocolExtensionHook g_register_native_service_protocol_extensions_hook = nullptr; void IsolateShutdownCallback(void* callback_data) { @@ -177,24 +174,16 @@ static bool StringEndsWith(const std::string& string, 0; } +Dart_Isolate ServiceIsolateCreateCallback(const char* script_uri, + char** error) { #if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_RELEASE - -Dart_Isolate ServiceIsolateCreateCallback(const char* script_uri, - char** error) { + // No VM-service in release mode. return nullptr; -} - #else // FLUTTER_RUNTIME_MODE - -Dart_Isolate ServiceIsolateCreateCallback(const char* script_uri, - char** error) { tonic::DartState* dart_state = new tonic::DartState(); Dart_Isolate isolate = Dart_CreateIsolate( - script_uri, "main", - reinterpret_cast(DART_SYMBOL(kDartIsolateSnapshotData)), - reinterpret_cast( - DART_SYMBOL(kDartIsolateSnapshotInstructions)), - nullptr, dart_state, error); + 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(Dart_IsServiceIsolate(isolate)); @@ -228,9 +217,9 @@ Dart_Isolate ServiceIsolateCreateCallback(const char* script_uri, IsRunningPrecompiledCode()); } return isolate; +#endif // FLUTTER_RUNTIME_MODE } -#endif // FLUTTER_RUNTIME_MODE Dart_Isolate IsolateCreateCallback(const char* script_uri, const char* main, @@ -275,10 +264,8 @@ Dart_Isolate IsolateCreateCallback(const char* script_uri, UIDartState* dart_state = parent_dart_state->CreateForChildIsolate(); Dart_Isolate isolate = Dart_CreateIsolate( - script_uri, main, - reinterpret_cast(DART_SYMBOL(kDartIsolateSnapshotData)), - reinterpret_cast(DART_SYMBOL(kDartIsolateSnapshotInstructions)), - nullptr, dart_state, error); + 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( @@ -360,148 +347,10 @@ static void ServiceStreamCancelCallback(const char* stream_id) { } // namespace -#if DART_ALLOW_DYNAMIC_RESOLUTION - -constexpr char kDartVmSnapshotDataName[] = "kDartVmSnapshotData"; -constexpr char kDartVmSnapshotInstructionsName[] = - "kDartVmSnapshotInstructions"; -constexpr char kDartIsolateSnapshotDataName[] = "kDartIsolateSnapshotData"; -constexpr char kDartIsolateSnapshotInstructionsName[] = - "kDartIsolateSnapshotInstructions"; - -#if OS(IOS) - -const char* kDartApplicationLibraryPath = "app.dylib"; - -static void* DartLookupSymbolInLibrary(const char* symbol_name, - const char* library) { - TRACE_EVENT0("flutter", __func__); - if (symbol_name == nullptr) { - return nullptr; - } - dlerror(); // clear previous errors on thread - void* library_handle = dlopen(library, RTLD_NOW); - if (dlerror() != nullptr) { - return nullptr; - } - void* sym = dlsym(library_handle, symbol_name); - return dlerror() != nullptr ? nullptr : sym; -} - -void* _DartSymbolLookup(const char* symbol_name) { - TRACE_EVENT0("flutter", __func__); - if (symbol_name == nullptr) { - return nullptr; - } - - const char* application_library_path = kDartApplicationLibraryPath; - const Settings& settings = Settings::Get(); - const std::string& application_library_path_setting = - settings.application_library_path; - if (!application_library_path_setting.empty()) { - application_library_path = application_library_path_setting.c_str(); - } - - // First the application library is checked for the valid symbols. This - // library may not necessarily exist. If it does exist, it is loaded and the - // symbols resolved. Once the application library is loaded, there is - // currently no provision to unload the same. - void* symbol = - DartLookupSymbolInLibrary(symbol_name, application_library_path); - if (symbol != nullptr) { - return symbol; - } - - // Check inside the default library - return DartLookupSymbolInLibrary(symbol_name, nullptr); -} - -#elif OS(ANDROID) - -// Describes an asset file that holds a part of the precompiled snapshot. -struct SymbolAsset { - const char* symbol_name; - const char* file_name; - bool is_executable; - size_t settings_offset; - void* mapping; -}; - -static SymbolAsset g_symbol_assets[] = { - {kDartVmSnapshotDataName, "vm_snapshot_data", false, - offsetof(Settings, aot_vm_snapshot_data_filename)}, - {kDartVmSnapshotInstructionsName, "vm_snapshot_instr", true, - offsetof(Settings, aot_vm_snapshot_instr_filename)}, - {kDartIsolateSnapshotDataName, "isolate_snapshot_data", false, - offsetof(Settings, aot_isolate_snapshot_data_filename)}, - {kDartIsolateSnapshotInstructionsName, "isolate_snapshot_instr", true, - offsetof(Settings, aot_isolate_snapshot_instr_filename)}, -}; - -// Resolve a precompiled snapshot symbol by mapping the corresponding asset -// file into memory. -void* _DartSymbolLookup(const char* symbol_name) { - for (SymbolAsset& symbol_asset : g_symbol_assets) { - if (strcmp(symbol_name, symbol_asset.symbol_name)) - continue; - - if (symbol_asset.mapping) { - return symbol_asset.mapping; - } - - const Settings& settings = Settings::Get(); - const std::string& aot_snapshot_path = settings.aot_snapshot_path; - FTL_CHECK(!aot_snapshot_path.empty()); - - const char* file_name = symbol_asset.file_name; - const std::string* settings_override = reinterpret_cast( - reinterpret_cast(&settings) + - symbol_asset.settings_offset); - if (!settings_override->empty()) - file_name = settings_override->c_str(); - - std::string asset_path = aot_snapshot_path + "/" + file_name; - struct stat info; - if (stat(asset_path.c_str(), &info) < 0) - return nullptr; - int64_t asset_size = info.st_size; - - ftl::UniqueFD fd(HANDLE_EINTR(open(asset_path.c_str(), O_RDONLY))); - if (fd.get() == -1) - return nullptr; - - int mmap_flags = PROT_READ; - if (symbol_asset.is_executable) - mmap_flags |= PROT_EXEC; - - void* symbol = mmap(NULL, asset_size, mmap_flags, MAP_PRIVATE, fd.get(), 0); - symbol_asset.mapping = symbol == MAP_FAILED ? nullptr : symbol; - - return symbol_asset.mapping; - } - - return nullptr; -} - -#else - -#error "AOT mode is not supported on this platform" - -#endif - bool IsRunningPrecompiledCode() { - TRACE_EVENT0("flutter", __func__); return Dart_IsPrecompiledRuntime(); } -#else // DART_ALLOW_DYNAMIC_RESOLUTION - -bool IsRunningPrecompiledCode() { - return false; -} - -#endif // DART_ALLOW_DYNAMIC_RESOLUTION - EmbedderTracingCallbacks* g_tracing_callbacks = nullptr; EmbedderTracingCallbacks::EmbedderTracingCallbacks( @@ -567,9 +416,16 @@ void PushBackAll(std::vector* args, } } -void InitDartVM() { +void InitDartVM(const uint8_t* vm_snapshot_data, + const uint8_t* vm_snapshot_instructions, + const uint8_t* default_isolate_snapshot_data, + const uint8_t* default_isolate_snapshot_instructions) { TRACE_EVENT0("flutter", __func__); + g_default_isolate_snapshot_data = default_isolate_snapshot_data; + g_default_isolate_snapshot_instructions = + default_isolate_snapshot_instructions; + const Settings& settings = Settings::Get(); { @@ -642,7 +498,7 @@ void InitDartVM() { FTL_CHECK(Dart_SetVMFlags(args.size(), args.data())); #if FLUTTER_RUNTIME_MODE != FLUTTER_RUNTIME_MODE_RELEASE - { + if (!IsRunningPrecompiledCode()) { TRACE_EVENT0("flutter", "DartDebugger::InitDebugger"); // This should be called before calling Dart_Initialize. tonic::DartDebugger::InitDebugger(); @@ -662,10 +518,8 @@ void InitDartVM() { TRACE_EVENT0("flutter", "Dart_Initialize"); Dart_InitializeParams params = {}; params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION; - params.vm_snapshot_data = - reinterpret_cast(DART_SYMBOL(kDartVmSnapshotData)); - params.vm_snapshot_instructions = - reinterpret_cast(DART_SYMBOL(kDartVmSnapshotInstructions)); + params.vm_snapshot_data = vm_snapshot_data; + params.vm_snapshot_instructions = vm_snapshot_instructions; params.create = IsolateCreateCallback; params.shutdown = IsolateShutdownCallback; params.thread_exit = ThreadExitCallback; diff --git a/runtime/dart_init.h b/runtime/dart_init.h index 6a7afeeb3c7..85ecaeca8e7 100644 --- a/runtime/dart_init.h +++ b/runtime/dart_init.h @@ -14,32 +14,6 @@ namespace blink { -#define DART_ALLOW_DYNAMIC_RESOLUTION (OS_IOS || FLUTTER_AOT) - -#if DART_ALLOW_DYNAMIC_RESOLUTION - -extern const char kDartVmSnapshotDataName[]; -extern const char kDartVmSnapshotInstructionsName[]; -extern const char kDartIsolateSnapshotDataName[]; -extern const char kDartIsolateSnapshotInstructionsName[]; - -void* _DartSymbolLookup(const char* symbol_name); - -#define DART_SYMBOL(symbol) _DartSymbolLookup(symbol##Name) - -#else // DART_ALLOW_DYNAMIC_RESOLUTION - -extern "C" { -extern void* kDartVmSnapshotData; -extern void* kDartVmSnapshotInstructions; -extern void* kDartIsolateSnapshotData; -extern void* kDartIsolateSnapshotInstructions; -} - -#define DART_SYMBOL(symbol) (&symbol) - -#endif // DART_ALLOW_DYNAMIC_RESOLUTION - // Name of the kernel blob asset within the FLX bundle. extern const char kKernelAssetKey[]; @@ -61,7 +35,10 @@ struct EmbedderTracingCallbacks { EmbedderTracingCallback stop); }; -void InitDartVM(); +void InitDartVM(const uint8_t* vm_snapshot_data, + const uint8_t* vm_snapshot_instructions, + const uint8_t* default_isolate_snapshot_data, + const uint8_t* default_isolate_snapshot_instructions); void SetEmbedderTracingCallbacks( std::unique_ptr callbacks); diff --git a/runtime/dart_vm_entry_points_fuchsia.txt b/runtime/dart_vm_entry_points_fuchsia.txt new file mode 100644 index 00000000000..3c7d03aa362 --- /dev/null +++ b/runtime/dart_vm_entry_points_fuchsia.txt @@ -0,0 +1,4 @@ +dart:fidl.internal,::,_environment +dart:fidl.internal,::,_outgoingServices +dart:fidl.internal,HandleWaiter,onWaitComplete +dart:mozart.internal,::,_viewContainer diff --git a/runtime/runtime_controller.cc b/runtime/runtime_controller.cc index 3e143cd6bcf..bf9586ef1a4 100644 --- a/runtime/runtime_controller.cc +++ b/runtime/runtime_controller.cc @@ -26,12 +26,14 @@ RuntimeController::RuntimeController(RuntimeDelegate* client) RuntimeController::~RuntimeController() {} -void RuntimeController::CreateDartController(const std::string& script_uri) { +void RuntimeController::CreateDartController( + const std::string& script_uri, const uint8_t* isolate_snapshot_data, + const uint8_t* isolate_snapshot_instr) { FTL_DCHECK(!dart_controller_); dart_controller_.reset(new DartController()); dart_controller_->CreateIsolateFor( - script_uri, + script_uri, isolate_snapshot_data, isolate_snapshot_instr, std::make_unique(this, std::make_unique(this))); UIDartState* dart_state = dart_controller_->dart_state(); diff --git a/runtime/runtime_controller.h b/runtime/runtime_controller.h index 941673c683c..7f2fadf0dff 100644 --- a/runtime/runtime_controller.h +++ b/runtime/runtime_controller.h @@ -26,7 +26,9 @@ class RuntimeController : public WindowClient, public IsolateClient { static std::unique_ptr Create(RuntimeDelegate* client); ~RuntimeController(); - void CreateDartController(const std::string& script_uri); + void CreateDartController(const std::string& script_uri, + const uint8_t* isolate_snapshot_data, + const uint8_t* isolate_snapshot_instr); DartController* dart_controller() const { return dart_controller_.get(); } void SetViewportMetrics(const ViewportMetrics& metrics); diff --git a/runtime/runtime_init.cc b/runtime/runtime_init.cc index 0ae35a19573..b25e5b0edba 100644 --- a/runtime/runtime_init.cc +++ b/runtime/runtime_init.cc @@ -17,13 +17,18 @@ PlatformImpl* g_platform_impl = nullptr; } // namespace -void InitRuntime() { +void InitRuntime(const uint8_t* vm_snapshot_data, + const uint8_t* vm_snapshot_instructions, + const uint8_t* default_isolate_snapshot_data, + const uint8_t* default_isolate_snapshot_instructions) { TRACE_EVENT0("flutter", "InitRuntime"); FTL_CHECK(!g_platform_impl); g_platform_impl = new PlatformImpl(); InitEngine(g_platform_impl); - InitDartVM(); + InitDartVM(vm_snapshot_data, vm_snapshot_instructions, + default_isolate_snapshot_data, + default_isolate_snapshot_instructions); } } // namespace blink diff --git a/runtime/runtime_init.h b/runtime/runtime_init.h index 4986def32e8..527570ca976 100644 --- a/runtime/runtime_init.h +++ b/runtime/runtime_init.h @@ -5,9 +5,14 @@ #ifndef FLUTTER_RUNTIME_RUNTIME_INIT_H_ #define FLUTTER_RUNTIME_RUNTIME_INIT_H_ +#include + namespace blink { -void InitRuntime(); +void InitRuntime(const uint8_t* vm_snapshot_data, + const uint8_t* vm_snapshot_instructions, + const uint8_t* default_isolate_snapshot_data, + const uint8_t* default_isolate_snapshot_instructions); } // namespace blink diff --git a/shell/common/engine.cc b/shell/common/engine.cc index 60c1d27d325..b8a03c6aa9f 100644 --- a/shell/common/engine.cc +++ b/shell/common/engine.cc @@ -4,6 +4,9 @@ #include "flutter/shell/common/engine.h" +#include +#include +#include #include #include #include @@ -15,6 +18,7 @@ #include "flutter/common/settings.h" #include "flutter/common/threads.h" #include "flutter/glue/trace_event.h" +#include "flutter/lib/snapshot/snapshot.h" #include "flutter/runtime/asset_font_selector.h" #include "flutter/runtime/dart_controller.h" #include "flutter/runtime/dart_init.h" @@ -23,8 +27,10 @@ #include "flutter/shell/common/animator.h" #include "flutter/shell/common/platform_view.h" #include "flutter/sky/engine/public/web/Sky.h" +#include "lib/ftl/files/eintr_wrapper.h" #include "lib/ftl/files/file.h" #include "lib/ftl/files/path.h" +#include "lib/ftl/files/unique_fd.h" #include "lib/ftl/functional/make_copyable.h" #include "third_party/rapidjson/rapidjson/document.h" #include "third_party/skia/include/core/SkCanvas.h" @@ -77,8 +83,99 @@ ftl::WeakPtr Engine::GetWeakPtr() { return weak_factory_.GetWeakPtr(); } +#if !FLUTTER_AOT +#elif OS(IOS) +#elif OS(ANDROID) +static const uint8_t* MemMapSnapshot(const std::string& aot_snapshot_path, + const std::string& default_file_name, + const std::string& settings_file_name, + bool executable) { + std::string asset_path; + if (settings_file_name.empty()) { + asset_path = aot_snapshot_path + "/" + default_file_name; + } else { + asset_path = aot_snapshot_path + "/" + settings_file_name; + } + + struct stat info; + if (stat(asset_path.c_str(), &info) < 0) { + return nullptr; + } + int64_t asset_size = info.st_size; + + ftl::UniqueFD fd(HANDLE_EINTR(open(asset_path.c_str(), O_RDONLY))); + if (fd.get() == -1) { + return nullptr; + } + + int mmap_flags = PROT_READ; + if (executable) mmap_flags |= PROT_EXEC; + + void* symbol = mmap(NULL, asset_size, mmap_flags, MAP_PRIVATE, fd.get(), 0); + if (symbol == MAP_FAILED) { + return nullptr; + } + return reinterpret_cast(symbol); +} +#endif + +static const uint8_t* default_isolate_snapshot_data = nullptr; +static const uint8_t* default_isolate_snapshot_instr = nullptr; + void Engine::Init() { - blink::InitRuntime(); + const uint8_t* vm_snapshot_data; + const uint8_t* vm_snapshot_instr; +#if !FLUTTER_AOT + vm_snapshot_data = ::kDartVmSnapshotData; + vm_snapshot_instr = ::kDartVmSnapshotInstructions; + default_isolate_snapshot_data = ::kDartIsolateCoreSnapshotData; + default_isolate_snapshot_instr = ::kDartIsolateCoreSnapshotInstructions; +#elif OS(IOS) + const char* kDartApplicationLibraryPath = "App.framework/App"; + const char* application_library_path = kDartApplicationLibraryPath; + const blink::Settings& settings = blink::Settings::Get(); + const std::string& application_library_path_setting = + settings.application_library_path; + if (!application_library_path_setting.empty()) { + application_library_path = application_library_path_setting.c_str(); + } + dlerror(); // clear previous errors on thread + void* library_handle = dlopen(application_library_path, RTLD_NOW); + const char* err = dlerror(); + if (err != nullptr) { + FTL_LOG(FATAL) << "dlopen failed: " << err; + } + vm_snapshot_data = reinterpret_cast( + dlsym(library_handle, "kDartVmSnapshotData")); + vm_snapshot_instr = reinterpret_cast( + dlsym(library_handle, "kDartVmSnapshotInstructions")); + default_isolate_snapshot_data = reinterpret_cast( + dlsym(library_handle, "kDartIsolateSnapshotData")); + default_isolate_snapshot_instr = reinterpret_cast( + dlsym(library_handle, "kDartIsolateSnapshotInstructions")); +#elif OS(ANDROID) + const blink::Settings& settings = blink::Settings::Get(); + const std::string& aot_snapshot_path = settings.aot_snapshot_path; + FTL_CHECK(!aot_snapshot_path.empty()); + vm_snapshot_data = + MemMapSnapshot(aot_snapshot_path, "vm_snapshot_data", + settings.aot_vm_snapshot_data_filename, false); + vm_snapshot_instr = + MemMapSnapshot(aot_snapshot_path, "vm_snapshot_instr", + settings.aot_vm_snapshot_instr_filename, true); + default_isolate_snapshot_data = + MemMapSnapshot(aot_snapshot_path, "isolate_snapshot_data", + settings.aot_isolate_snapshot_data_filename, false); + default_isolate_snapshot_instr = + MemMapSnapshot(aot_snapshot_path, "isolate_snapshot_instr", + settings.aot_isolate_snapshot_instr_filename, true); +#else +#error Unknown OS +#endif + + blink::InitRuntime(vm_snapshot_data, vm_snapshot_instr, + default_isolate_snapshot_data, + default_isolate_snapshot_instr); } void Engine::RunBundle(const std::string& bundle_path) { @@ -96,8 +193,8 @@ void Engine::RunBundle(const std::string& bundle_path) { std::vector snapshot; if (!GetAssetAsBuffer(blink::kSnapshotAssetKey, &snapshot)) return; - runtime_->dart_controller()->RunFromSnapshot(snapshot.data(), - snapshot.size()); + runtime_->dart_controller()->RunFromScriptSnapshot(snapshot.data(), + snapshot.size()); } } @@ -116,8 +213,8 @@ void Engine::RunBundleAndSnapshot(const std::string& bundle_path, std::vector snapshot; if (!files::ReadFileToVector(snapshot_override, &snapshot)) return; - runtime_->dart_controller()->RunFromSnapshot(snapshot.data(), - snapshot.size()); + runtime_->dart_controller()->RunFromScriptSnapshot(snapshot.data(), + snapshot.size()); } } @@ -322,7 +419,9 @@ void Engine::ConfigureAssetBundle(const std::string& path) { void Engine::ConfigureRuntime(const std::string& script_uri) { runtime_ = blink::RuntimeController::Create(this); - runtime_->CreateDartController(std::move(script_uri)); + runtime_->CreateDartController(std::move(script_uri), + default_isolate_snapshot_data, + default_isolate_snapshot_instr); runtime_->SetViewportMetrics(viewport_metrics_); runtime_->SetLocale(language_code_, country_code_); runtime_->SetSemanticsEnabled(semantics_enabled_); diff --git a/travis/licenses_golden/licenses_flutter b/travis/licenses_golden/licenses_flutter index ad0b5617cbe..4ef778c2c77 100644 --- a/travis/licenses_golden/licenses_flutter +++ b/travis/licenses_golden/licenses_flutter @@ -1520,6 +1520,7 @@ FILE: ../../../flutter/flow/layers/transform_layer.cc FILE: ../../../flutter/flow/layers/transform_layer.h FILE: ../../../flutter/lib/snapshot/snapshot.c.tmpl FILE: ../../../flutter/lib/snapshot/snapshot.dart +FILE: ../../../flutter/lib/snapshot/snapshot.h FILE: ../../../flutter/lib/snapshot/snapshot_fuchsia.dart FILE: ../../../flutter/lib/ui/compositing.dart FILE: ../../../flutter/lib/ui/compositing/scene.cc