#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";
#define DART_SNAPSHOT_STATIC_LINK \
(OS_WIN || (OS_ANDROID && FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG))
#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);
}
}
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) {
if (embedder_mapping_callback) {
return embedder_mapping_callback();
}
if (file_path.size() > 0) {
if (auto file_mapping = GetFileMapping(file_path, is_executable)) {
return file_mapping;
}
}
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;
}
}
{
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
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
return SearchMapping(
settings.vm_snapshot_data,
settings.vm_snapshot_data_path,
settings.application_library_path,
DartSnapshot::kVMDataSymbol,
false
);
#endif
}
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
return SearchMapping(
settings.vm_snapshot_instr,
settings.vm_snapshot_instr_path,
settings.application_library_path,
DartSnapshot::kVMInstructionsSymbol,
true
);
#endif
}
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
return SearchMapping(
settings.isolate_snapshot_data,
settings.isolate_snapshot_data_path,
settings.application_library_path,
DartSnapshot::kIsolateDataSymbol,
false
);
#endif
}
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
return SearchMapping(
settings.isolate_snapshot_instr,
settings.isolate_snapshot_instr_path,
settings.application_library_path,
DartSnapshot::kIsolateInstructionsSymbol,
true
);
#endif
}
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;
}
fml::RefPtr<DartSnapshot> DartSnapshot::Empty() {
return fml::MakeRefCounted<DartSnapshot>(nullptr, 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;
}
}