mirror of
https://github.com/encounter/engine.git
synced 2026-03-30 11:09:55 -07:00
206 lines
7.6 KiB
C++
206 lines
7.6 KiB
C++
// 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.
|
|
|
|
#include "flutter/runtime/dart_snapshot.h"
|
|
|
|
#include <sstream>
|
|
|
|
#include "flutter/fml/native_library.h"
|
|
#include "flutter/fml/paths.h"
|
|
#include "flutter/fml/trace_event.h"
|
|
#include "flutter/lib/snapshot/snapshot.h"
|
|
#include "flutter/runtime/dart_vm.h"
|
|
|
|
namespace flutter {
|
|
|
|
const char* DartSnapshot::kVMDataSymbol = "kDartVmSnapshotData";
|
|
const char* DartSnapshot::kVMInstructionsSymbol = "kDartVmSnapshotInstructions";
|
|
const char* DartSnapshot::kIsolateDataSymbol = "kDartIsolateSnapshotData";
|
|
const char* DartSnapshot::kIsolateInstructionsSymbol =
|
|
"kDartIsolateSnapshotInstructions";
|
|
|
|
// On Windows and Android (in debug mode) the engine finds the Dart snapshot
|
|
// data through symbols that are statically linked into the executable.
|
|
// On other platforms this data is obtained by a dynamic symbol lookup.
|
|
#define DART_SNAPSHOT_STATIC_LINK \
|
|
(OS_WIN || (OS_ANDROID && FLUTTER_JIT_RUNTIME))
|
|
|
|
#if !DART_SNAPSHOT_STATIC_LINK
|
|
|
|
static std::unique_ptr<const fml::Mapping> GetFileMapping(
|
|
const std::string& path,
|
|
bool executable) {
|
|
if (executable) {
|
|
return fml::FileMapping::CreateReadExecute(path);
|
|
} else {
|
|
return fml::FileMapping::CreateReadOnly(path);
|
|
}
|
|
}
|
|
|
|
// The first party embedders don't yet use the stable embedder API and depend on
|
|
// the engine figuring out the locations of the various heap and instructions
|
|
// buffers. Consequently, the engine had baked in opinions about where these
|
|
// buffers would reside and how they would be packaged (examples, in an external
|
|
// dylib, in the same dylib, at a path, at a path relative to and FD, etc..). As
|
|
// the needs of the platforms changed, the lack of an API meant that the engine
|
|
// had to be patched to look for new fields in the settings object. This grew
|
|
// untenable and with the addition of the new Fuchsia embedder and the generic C
|
|
// embedder API, embedders could specify the mapping directly. Once everyone
|
|
// moves to the embedder API, this method can effectively be reduced to just
|
|
// invoking the embedder_mapping_callback directly.
|
|
static std::shared_ptr<const fml::Mapping> SearchMapping(
|
|
MappingCallback embedder_mapping_callback,
|
|
const std::string& file_path,
|
|
const std::vector<std::string>& native_library_path,
|
|
const char* native_library_symbol_name,
|
|
bool is_executable) {
|
|
// Ask the embedder. There is no fallback as we expect the embedders (via
|
|
// their embedding APIs) to just specify the mappings directly.
|
|
if (embedder_mapping_callback) {
|
|
return embedder_mapping_callback();
|
|
}
|
|
|
|
// Attempt to open file at path specified.
|
|
if (file_path.size() > 0) {
|
|
if (auto file_mapping = GetFileMapping(file_path, is_executable)) {
|
|
return file_mapping;
|
|
}
|
|
}
|
|
|
|
// Look in application specified native library if specified.
|
|
for (const std::string& path : native_library_path) {
|
|
auto native_library = fml::NativeLibrary::Create(path.c_str());
|
|
auto symbol_mapping = std::make_unique<const fml::SymbolMapping>(
|
|
native_library, native_library_symbol_name);
|
|
if (symbol_mapping->GetMapping() != nullptr) {
|
|
return symbol_mapping;
|
|
}
|
|
}
|
|
|
|
// Look inside the currently loaded process.
|
|
{
|
|
auto loaded_process = fml::NativeLibrary::CreateForCurrentProcess();
|
|
auto symbol_mapping = std::make_unique<const fml::SymbolMapping>(
|
|
loaded_process, native_library_symbol_name);
|
|
if (symbol_mapping->GetMapping() != nullptr) {
|
|
return symbol_mapping;
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
#endif // !DART_SNAPSHOT_STATIC_LINK
|
|
|
|
static std::shared_ptr<const fml::Mapping> ResolveVMData(
|
|
const Settings& settings) {
|
|
#if DART_SNAPSHOT_STATIC_LINK
|
|
return std::make_unique<fml::NonOwnedMapping>(kDartVmSnapshotData, 0);
|
|
#else // DART_SNAPSHOT_STATIC_LINK
|
|
return SearchMapping(
|
|
settings.vm_snapshot_data, // embedder_mapping_callback
|
|
settings.vm_snapshot_data_path, // file_path
|
|
settings.application_library_path, // native_library_path
|
|
DartSnapshot::kVMDataSymbol, // native_library_symbol_name
|
|
false // is_executable
|
|
);
|
|
#endif // DART_SNAPSHOT_STATIC_LINK
|
|
}
|
|
|
|
static std::shared_ptr<const fml::Mapping> ResolveVMInstructions(
|
|
const Settings& settings) {
|
|
#if DART_SNAPSHOT_STATIC_LINK
|
|
return std::make_unique<fml::NonOwnedMapping>(kDartVmSnapshotInstructions, 0);
|
|
#else // DART_SNAPSHOT_STATIC_LINK
|
|
return SearchMapping(
|
|
settings.vm_snapshot_instr, // embedder_mapping_callback
|
|
settings.vm_snapshot_instr_path, // file_path
|
|
settings.application_library_path, // native_library_path
|
|
DartSnapshot::kVMInstructionsSymbol, // native_library_symbol_name
|
|
true // is_executable
|
|
);
|
|
#endif // DART_SNAPSHOT_STATIC_LINK
|
|
}
|
|
|
|
static std::shared_ptr<const fml::Mapping> ResolveIsolateData(
|
|
const Settings& settings) {
|
|
#if DART_SNAPSHOT_STATIC_LINK
|
|
return std::make_unique<fml::NonOwnedMapping>(kDartIsolateSnapshotData, 0);
|
|
#else // DART_SNAPSHOT_STATIC_LINK
|
|
return SearchMapping(
|
|
settings.isolate_snapshot_data, // embedder_mapping_callback
|
|
settings.isolate_snapshot_data_path, // file_path
|
|
settings.application_library_path, // native_library_path
|
|
DartSnapshot::kIsolateDataSymbol, // native_library_symbol_name
|
|
false // is_executable
|
|
);
|
|
#endif // DART_SNAPSHOT_STATIC_LINK
|
|
}
|
|
|
|
static std::shared_ptr<const fml::Mapping> ResolveIsolateInstructions(
|
|
const Settings& settings) {
|
|
#if DART_SNAPSHOT_STATIC_LINK
|
|
return std::make_unique<fml::NonOwnedMapping>(
|
|
kDartIsolateSnapshotInstructions, 0);
|
|
#else // DART_SNAPSHOT_STATIC_LINK
|
|
return SearchMapping(
|
|
settings.isolate_snapshot_instr, // embedder_mapping_callback
|
|
settings.isolate_snapshot_instr_path, // file_path
|
|
settings.application_library_path, // native_library_path
|
|
DartSnapshot::kIsolateInstructionsSymbol, // native_library_symbol_name
|
|
true // is_executable
|
|
);
|
|
#endif // DART_SNAPSHOT_STATIC_LINK
|
|
}
|
|
|
|
fml::RefPtr<DartSnapshot> DartSnapshot::VMSnapshotFromSettings(
|
|
const Settings& settings) {
|
|
TRACE_EVENT0("flutter", "DartSnapshot::VMSnapshotFromSettings");
|
|
auto snapshot =
|
|
fml::MakeRefCounted<DartSnapshot>(ResolveVMData(settings), //
|
|
ResolveVMInstructions(settings) //
|
|
);
|
|
if (snapshot->IsValid()) {
|
|
return snapshot;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
fml::RefPtr<DartSnapshot> DartSnapshot::IsolateSnapshotFromSettings(
|
|
const Settings& settings) {
|
|
TRACE_EVENT0("flutter", "DartSnapshot::IsolateSnapshotFromSettings");
|
|
auto snapshot =
|
|
fml::MakeRefCounted<DartSnapshot>(ResolveIsolateData(settings), //
|
|
ResolveIsolateInstructions(settings) //
|
|
);
|
|
if (snapshot->IsValid()) {
|
|
return snapshot;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
DartSnapshot::DartSnapshot(std::shared_ptr<const fml::Mapping> data,
|
|
std::shared_ptr<const fml::Mapping> instructions)
|
|
: data_(std::move(data)), instructions_(std::move(instructions)) {}
|
|
|
|
DartSnapshot::~DartSnapshot() = default;
|
|
|
|
bool DartSnapshot::IsValid() const {
|
|
return static_cast<bool>(data_);
|
|
}
|
|
|
|
bool DartSnapshot::IsValidForAOT() const {
|
|
return data_ && instructions_;
|
|
}
|
|
|
|
const uint8_t* DartSnapshot::GetDataMapping() const {
|
|
return data_ ? data_->GetMapping() : nullptr;
|
|
}
|
|
|
|
const uint8_t* DartSnapshot::GetInstructionsMapping() const {
|
|
return instructions_ ? instructions_->GetMapping() : nullptr;
|
|
}
|
|
|
|
} // namespace flutter
|