mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Build a specialized snapshot for launching the service isolate in profile mode on Android (flutter/engine#29245)
This commit is contained in:
parent
4c441b59f6
commit
2c8702d096
@ -31,6 +31,9 @@ frontend_server_files +=
|
||||
#
|
||||
# Invoker must supply dart_main and package_config. Invoker may optionally
|
||||
# supply aot as a boolean and product as a boolean.
|
||||
#
|
||||
# On Android, the invoker may provide output_aot_lib as a string to override
|
||||
# the default filename for the aot-elf snapshot.
|
||||
template("flutter_snapshot") {
|
||||
assert(!is_fuchsia)
|
||||
assert(defined(invoker.main_dart), "main_dart is a required parameter.")
|
||||
@ -134,7 +137,12 @@ template("flutter_snapshot") {
|
||||
"--assembly=" + rebase_path(snapshot_assembly),
|
||||
]
|
||||
} else if (is_android) {
|
||||
libapp = "$target_gen_dir/android/libs/$android_app_abi/libapp.so"
|
||||
if (defined(invoker.output_aot_lib)) {
|
||||
output_aot_lib = invoker.output_aot_lib
|
||||
} else {
|
||||
output_aot_lib = "libapp.so"
|
||||
}
|
||||
libapp = "$target_gen_dir/android/libs/$android_app_abi/$output_aot_lib"
|
||||
outputs += [ libapp ]
|
||||
args += [
|
||||
"--snapshot_kind=app-aot-elf",
|
||||
|
||||
@ -1794,6 +1794,7 @@ FILE: ../../../flutter/shell/profiling/sampling_profiler.h
|
||||
FILE: ../../../flutter/shell/profiling/sampling_profiler_unittest.cc
|
||||
FILE: ../../../flutter/shell/version/version.cc
|
||||
FILE: ../../../flutter/shell/version/version.h
|
||||
FILE: ../../../flutter/shell/vmservice/empty.dart
|
||||
FILE: ../../../flutter/sky/tools/roll/patches/chromium/android_build.patch
|
||||
FILE: ../../../flutter/third_party/accessibility/base/color_utils.h
|
||||
FILE: ../../../flutter/third_party/accessibility/base/compiler_specific.h
|
||||
|
||||
@ -116,6 +116,10 @@ struct Settings {
|
||||
// case the primary path to the library can not be loaded.
|
||||
std::vector<std::string> application_library_path;
|
||||
|
||||
// Path to a library containing compiled Dart code usable for launching
|
||||
// the VM service isolate.
|
||||
std::vector<std::string> vmservice_snapshot_library_path;
|
||||
|
||||
std::string application_kernel_asset; // deprecated
|
||||
std::string application_kernel_list_asset; // deprecated
|
||||
MappingsCallback application_kernels;
|
||||
|
||||
@ -838,8 +838,7 @@ Dart_Isolate DartIsolate::DartCreateAndStartServiceIsolate(
|
||||
// TODO(68663): The service isolate in debug mode is always launched without
|
||||
// sound null safety. Fix after the isolate snapshot data is created with the
|
||||
// right flags.
|
||||
flags->null_safety =
|
||||
vm_data->GetIsolateSnapshot()->IsNullSafetyEnabled(nullptr);
|
||||
flags->null_safety = vm_data->GetServiceIsolateSnapshotNullSafety();
|
||||
#endif
|
||||
|
||||
UIDartState::Context context(
|
||||
@ -848,13 +847,13 @@ Dart_Isolate DartIsolate::DartCreateAndStartServiceIsolate(
|
||||
context.advisory_script_uri = DART_VM_SERVICE_ISOLATE_NAME;
|
||||
context.advisory_script_entrypoint = DART_VM_SERVICE_ISOLATE_NAME;
|
||||
std::weak_ptr<DartIsolate> weak_service_isolate =
|
||||
DartIsolate::CreateRootIsolate(vm_data->GetSettings(), //
|
||||
vm_data->GetIsolateSnapshot(), //
|
||||
nullptr, //
|
||||
DartIsolate::Flags{flags}, //
|
||||
nullptr, //
|
||||
nullptr, //
|
||||
context); //
|
||||
DartIsolate::CreateRootIsolate(vm_data->GetSettings(), //
|
||||
vm_data->GetServiceIsolateSnapshot(), //
|
||||
nullptr, //
|
||||
DartIsolate::Flags{flags}, //
|
||||
nullptr, //
|
||||
nullptr, //
|
||||
context); //
|
||||
|
||||
std::shared_ptr<DartIsolate> service_isolate = weak_service_isolate.lock();
|
||||
if (!service_isolate) {
|
||||
|
||||
@ -192,6 +192,25 @@ fml::RefPtr<DartSnapshot> DartSnapshot::IsolateSnapshotFromMappings(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
fml::RefPtr<DartSnapshot> DartSnapshot::VMServiceIsolateSnapshotFromSettings(
|
||||
const Settings& settings) {
|
||||
#if DART_SNAPSHOT_STATIC_LINK
|
||||
return nullptr;
|
||||
#else // DART_SNAPSHOT_STATIC_LINK
|
||||
if (settings.vmservice_snapshot_library_path.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<const fml::Mapping> snapshot_data =
|
||||
SearchMapping(nullptr, "", settings.vmservice_snapshot_library_path,
|
||||
DartSnapshot::kIsolateDataSymbol, false);
|
||||
std::shared_ptr<const fml::Mapping> snapshot_instructions =
|
||||
SearchMapping(nullptr, "", settings.vmservice_snapshot_library_path,
|
||||
DartSnapshot::kIsolateInstructionsSymbol, true);
|
||||
return IsolateSnapshotFromMappings(snapshot_data, snapshot_instructions);
|
||||
#endif // DART_SNAPSHOT_STATIC_LINK
|
||||
}
|
||||
|
||||
DartSnapshot::DartSnapshot(std::shared_ptr<const fml::Mapping> data,
|
||||
std::shared_ptr<const fml::Mapping> instructions)
|
||||
: data_(std::move(data)), instructions_(std::move(instructions)) {}
|
||||
|
||||
@ -114,6 +114,15 @@ class DartSnapshot : public fml::RefCountedThreadSafe<DartSnapshot> {
|
||||
std::shared_ptr<const fml::Mapping> snapshot_data,
|
||||
std::shared_ptr<const fml::Mapping> snapshot_instructions);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Create an isolate snapshot specialized for launching the
|
||||
/// service isolate. Returns nullptr if no such snapshot is
|
||||
/// available.
|
||||
///
|
||||
/// @return A valid isolate snapshot or nullptr.
|
||||
static fml::RefPtr<DartSnapshot> VMServiceIsolateSnapshotFromSettings(
|
||||
const Settings& settings);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Determines if this snapshot contains a heap component. Since
|
||||
/// the instructions component is optional, the method does not
|
||||
|
||||
@ -32,19 +32,25 @@ std::shared_ptr<const DartVMData> DartVMData::Create(
|
||||
}
|
||||
}
|
||||
|
||||
fml::RefPtr<const DartSnapshot> service_isolate_snapshot =
|
||||
DartSnapshot::VMServiceIsolateSnapshotFromSettings(settings);
|
||||
|
||||
return std::shared_ptr<const DartVMData>(new DartVMData(
|
||||
std::move(settings), //
|
||||
std::move(vm_snapshot), //
|
||||
std::move(isolate_snapshot) //
|
||||
std::move(settings), //
|
||||
std::move(vm_snapshot), //
|
||||
std::move(isolate_snapshot), //
|
||||
std::move(service_isolate_snapshot) //
|
||||
));
|
||||
}
|
||||
|
||||
DartVMData::DartVMData(Settings settings,
|
||||
fml::RefPtr<const DartSnapshot> vm_snapshot,
|
||||
fml::RefPtr<const DartSnapshot> isolate_snapshot)
|
||||
fml::RefPtr<const DartSnapshot> isolate_snapshot,
|
||||
fml::RefPtr<const DartSnapshot> service_isolate_snapshot)
|
||||
: settings_(settings),
|
||||
vm_snapshot_(vm_snapshot),
|
||||
isolate_snapshot_(isolate_snapshot) {}
|
||||
isolate_snapshot_(isolate_snapshot),
|
||||
service_isolate_snapshot_(service_isolate_snapshot) {}
|
||||
|
||||
DartVMData::~DartVMData() = default;
|
||||
|
||||
@ -60,4 +66,23 @@ fml::RefPtr<const DartSnapshot> DartVMData::GetIsolateSnapshot() const {
|
||||
return isolate_snapshot_;
|
||||
}
|
||||
|
||||
fml::RefPtr<const DartSnapshot> DartVMData::GetServiceIsolateSnapshot() const {
|
||||
// Use the specialized snapshot for the service isolate if the embedder
|
||||
// provides one. Otherwise, use the application snapshot.
|
||||
return service_isolate_snapshot_ ? service_isolate_snapshot_
|
||||
: isolate_snapshot_;
|
||||
}
|
||||
|
||||
bool DartVMData::GetServiceIsolateSnapshotNullSafety() const {
|
||||
if (service_isolate_snapshot_) {
|
||||
// The specialized snapshot for the service isolate is always built
|
||||
// using null safety. However, calling Dart_DetectNullSafety on
|
||||
// the service isolate snapshot will not work as expected - it will
|
||||
// instead return a cached value representing the app snapshot.
|
||||
return true;
|
||||
} else {
|
||||
return isolate_snapshot_->IsNullSafetyEnabled(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
@ -71,14 +71,32 @@ class DartVMData {
|
||||
///
|
||||
fml::RefPtr<const DartSnapshot> GetIsolateSnapshot() const;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Get the isolate snapshot used to launch the service isolate
|
||||
/// in the Dart VM.
|
||||
///
|
||||
/// @return The service isolate snapshot.
|
||||
///
|
||||
fml::RefPtr<const DartSnapshot> GetServiceIsolateSnapshot() const;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Returns whether the service isolate snapshot requires null
|
||||
/// safety in the Dart_IsolateFlags used to create the isolate.
|
||||
///
|
||||
/// @return True if the snapshot requires null safety.
|
||||
///
|
||||
bool GetServiceIsolateSnapshotNullSafety() const;
|
||||
|
||||
private:
|
||||
const Settings settings_;
|
||||
const fml::RefPtr<const DartSnapshot> vm_snapshot_;
|
||||
const fml::RefPtr<const DartSnapshot> isolate_snapshot_;
|
||||
const fml::RefPtr<const DartSnapshot> service_isolate_snapshot_;
|
||||
|
||||
DartVMData(Settings settings,
|
||||
fml::RefPtr<const DartSnapshot> vm_snapshot,
|
||||
fml::RefPtr<const DartSnapshot> isolate_snapshot);
|
||||
fml::RefPtr<const DartSnapshot> isolate_snapshot,
|
||||
fml::RefPtr<const DartSnapshot> service_isolate_snapshot);
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(DartVMData);
|
||||
};
|
||||
|
||||
@ -334,6 +334,13 @@ Settings SettingsFromCommandLine(const fml::CommandLine& command_line) {
|
||||
std::vector<std::string_view> aot_shared_library_name =
|
||||
command_line.GetOptionValues(FlagForSwitch(Switch::AotSharedLibraryName));
|
||||
|
||||
std::vector<std::string_view> vmservice_shared_library_name =
|
||||
command_line.GetOptionValues(
|
||||
FlagForSwitch(Switch::AotVMServiceSharedLibraryName));
|
||||
for (auto path : vmservice_shared_library_name) {
|
||||
settings.vmservice_snapshot_library_path.emplace_back(path);
|
||||
}
|
||||
|
||||
std::string snapshot_asset_path;
|
||||
command_line.GetOptionValue(FlagForSwitch(Switch::SnapshotAssetPath),
|
||||
&snapshot_asset_path);
|
||||
|
||||
@ -28,6 +28,10 @@ DEF_SWITCHES_START
|
||||
DEF_SWITCH(AotSharedLibraryName,
|
||||
"aot-shared-library-name",
|
||||
"Name of the *.so containing AOT compiled Dart assets.")
|
||||
DEF_SWITCH(AotVMServiceSharedLibraryName,
|
||||
"aot-vmservice-shared-library-name",
|
||||
"Name of the *.so containing AOT compiled Dart assets for "
|
||||
"launching the service isolate.")
|
||||
DEF_SWITCH(SnapshotAssetPath,
|
||||
"snapshot-asset-path",
|
||||
"Path to the directory containing the four files specified by "
|
||||
|
||||
@ -444,6 +444,17 @@ action("android_jar") {
|
||||
":pom_embedding",
|
||||
":pom_libflutter",
|
||||
]
|
||||
|
||||
if (flutter_runtime_mode == "profile") {
|
||||
deps += [ "//flutter/shell/vmservice:vmservice_snapshot" ]
|
||||
args += [
|
||||
"--native_lib",
|
||||
rebase_path(
|
||||
"$root_gen_dir/flutter/shell/vmservice/android/libs/$android_app_abi/libvmservice_snapshot.so",
|
||||
root_build_dir,
|
||||
root_build_dir),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
action("pom_libflutter") {
|
||||
|
||||
@ -42,6 +42,7 @@ public class FlutterLoader {
|
||||
|
||||
// Must match values in flutter::switches
|
||||
static final String AOT_SHARED_LIBRARY_NAME = "aot-shared-library-name";
|
||||
static final String AOT_VMSERVICE_SHARED_LIBRARY_NAME = "aot-vmservice-shared-library-name";
|
||||
static final String SNAPSHOT_ASSET_PATH_KEY = "snapshot-asset-path";
|
||||
static final String VM_SNAPSHOT_DATA_KEY = "vm-snapshot-data";
|
||||
static final String ISOLATE_SNAPSHOT_DATA_KEY = "isolate-snapshot-data";
|
||||
@ -51,6 +52,7 @@ public class FlutterLoader {
|
||||
// Resource names used for components of the precompiled snapshot.
|
||||
private static final String DEFAULT_LIBRARY = "libflutter.so";
|
||||
private static final String DEFAULT_KERNEL_BLOB = "kernel_blob.bin";
|
||||
private static final String VMSERVICE_SNAPSHOT_LIBRARY = "libvmservice_snapshot.so";
|
||||
|
||||
private static FlutterLoader instance;
|
||||
|
||||
@ -240,6 +242,13 @@ public class FlutterLoader {
|
||||
+ flutterApplicationInfo.nativeLibraryDir
|
||||
+ File.separator
|
||||
+ flutterApplicationInfo.aotSharedLibraryName);
|
||||
|
||||
// In profile mode, provide a separate library containing a snapshot for
|
||||
// launching the Dart VM service isolate.
|
||||
if (BuildConfig.PROFILE) {
|
||||
shellArgs.add(
|
||||
"--" + AOT_VMSERVICE_SHARED_LIBRARY_NAME + "=" + VMSERVICE_SNAPSHOT_LIBRARY);
|
||||
}
|
||||
}
|
||||
|
||||
shellArgs.add("--cache-dir-path=" + result.engineCachesPath);
|
||||
|
||||
12
engine/src/flutter/shell/vmservice/BUILD.gn
Normal file
12
engine/src/flutter/shell/vmservice/BUILD.gn
Normal file
@ -0,0 +1,12 @@
|
||||
# Copyright 2013 The Flutter 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("//flutter/build/dart/rules.gni")
|
||||
|
||||
# Build a minimal snapshot that can be used to launch the VM service isolate.
|
||||
flutter_snapshot("vmservice_snapshot") {
|
||||
main_dart = "empty.dart"
|
||||
package_config = ".dart_tool/package_config.json"
|
||||
output_aot_lib = "libvmservice_snapshot.so"
|
||||
}
|
||||
6
engine/src/flutter/shell/vmservice/empty.dart
Normal file
6
engine/src/flutter/shell/vmservice/empty.dart
Normal file
@ -0,0 +1,6 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// This is used to build an empty snapshot that can be used to start the VM service isolate.
|
||||
void main(List<String> args) {}
|
||||
8
engine/src/flutter/shell/vmservice/pubspec.yaml
Normal file
8
engine/src/flutter/shell/vmservice/pubspec.yaml
Normal file
@ -0,0 +1,8 @@
|
||||
# Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
name: vmservice_snapshot
|
||||
publish_to: none
|
||||
environment:
|
||||
sdk: '>=2.12.0 <3.0.0'
|
||||
@ -88,6 +88,18 @@ source_set("skia") {
|
||||
]
|
||||
}
|
||||
|
||||
dart_snapshot_kernel("vmservice_kernel") {
|
||||
dart_main =
|
||||
rebase_path("//flutter/shell/vmservice/empty.dart", root_build_dir)
|
||||
dart_kernel = "$target_gen_dir/assets/vmservice_kernel.bin"
|
||||
}
|
||||
|
||||
dart_snapshot_aot("vmservice_snapshot") {
|
||||
dart_kernel = "$target_gen_dir/assets/vmservice_kernel.bin"
|
||||
dart_elf_filename = "libvmservice_snapshot.so"
|
||||
deps = [ ":vmservice_kernel" ]
|
||||
}
|
||||
|
||||
source_set("fixture_test") {
|
||||
testonly = true
|
||||
|
||||
@ -103,6 +115,10 @@ source_set("fixture_test") {
|
||||
"//flutter/common",
|
||||
"//flutter/runtime",
|
||||
]
|
||||
|
||||
if (flutter_runtime_mode == "profile") {
|
||||
public_deps += [ ":vmservice_snapshot" ]
|
||||
}
|
||||
}
|
||||
|
||||
if (enable_unittests) {
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/testing/dart_fixture.h"
|
||||
#include "flutter/fml/paths.h"
|
||||
|
||||
namespace flutter::testing {
|
||||
|
||||
@ -48,6 +49,10 @@ void DartFixture::SetSnapshotsAndAssets(Settings& settings) {
|
||||
// snapshots will be present in the application AOT dylib.
|
||||
if (DartVM::IsRunningPrecompiledCode()) {
|
||||
FML_CHECK(PrepareSettingsForAOTWithSymbols(settings, aot_symbols_));
|
||||
#if OS_LINUX
|
||||
settings.vmservice_snapshot_library_path.emplace_back(fml::paths::JoinPaths(
|
||||
{GetTestingAssetsPath(), "libvmservice_snapshot.so"}));
|
||||
#endif // OS_LINUX
|
||||
} else {
|
||||
settings.application_kernels = [this]() -> Mappings {
|
||||
std::vector<std::unique_ptr<const fml::Mapping>> kernel_mappings;
|
||||
|
||||
@ -26,10 +26,16 @@ template("fixtures_location") {
|
||||
assert(defined(invoker.assets_dir), "The assets directory.")
|
||||
|
||||
location_path = rebase_path(invoker.assets_dir)
|
||||
testing_assets_path = rebase_path("$root_out_dir/gen/flutter/testing/assets")
|
||||
|
||||
# Array of source lines. We use a list to ensure a trailing newline is
|
||||
# emitted by write_file() to comply with -Wnewline-eof.
|
||||
location_source = [ "namespace flutter {namespace testing {const char* GetFixturesPath() {return \"$location_path\";}}}" ]
|
||||
location_source = [
|
||||
"namespace flutter { namespace testing { ",
|
||||
"const char* GetFixturesPath() {return \"$location_path\";} ",
|
||||
"const char* GetTestingAssetsPath() {return \"$testing_assets_path\";} ",
|
||||
"}}",
|
||||
]
|
||||
location_source_path = "$target_gen_dir/_fl_$target_name.cc"
|
||||
|
||||
write_file(location_source_path, location_source)
|
||||
|
||||
@ -27,6 +27,13 @@ namespace testing {
|
||||
///
|
||||
const char* GetFixturesPath();
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// @brief Returns the directory containing assets shared across all tests.
|
||||
///
|
||||
/// @return The testing assets path.
|
||||
///
|
||||
const char* GetTestingAssetsPath();
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// @brief Returns the default path to kernel_blob.bin. This file is within
|
||||
/// the directory returned by `GetFixturesPath()`.
|
||||
|
||||
@ -17,6 +17,7 @@ import sys
|
||||
ALL_PACKAGES = [
|
||||
os.path.join("src", "flutter", "ci"),
|
||||
os.path.join("src", "flutter", "flutter_frontend_server"),
|
||||
os.path.join("src", "flutter", "shell", "vmservice"),
|
||||
os.path.join("src", "flutter", "testing", "benchmark"),
|
||||
os.path.join("src", "flutter", "testing", "dart"),
|
||||
os.path.join("src", "flutter", "testing", "litetest"),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user