Replace AssetResolver GetAsBuffer with GetAsMapping. (flutter/engine#5546)

Toward no-copy loading of kernel.
This commit is contained in:
Ryan Macnak
2018-06-19 14:24:19 -07:00
committed by GitHub
parent ac0d77e6ab
commit e8df7055bc
26 changed files with 165 additions and 134 deletions

View File

@@ -34,19 +34,20 @@ void AssetManager::PushBack(std::unique_ptr<AssetResolver> resolver) {
}
// |blink::AssetResolver|
bool AssetManager::GetAsBuffer(const std::string& asset_name,
std::vector<uint8_t>* data) const {
std::unique_ptr<fml::Mapping> AssetManager::GetAsMapping(
const std::string& asset_name) const {
if (asset_name.size() == 0) {
return false;
return nullptr;
}
TRACE_EVENT0("flutter", "AssetManager::GetAsBuffer");
TRACE_EVENT0("flutter", "AssetManager::GetAsMapping");
for (const auto& resolver : resolvers_) {
if (resolver->GetAsBuffer(asset_name, data)) {
return true;
auto mapping = resolver->GetAsMapping(asset_name);
if (mapping != nullptr) {
return mapping;
}
}
FML_DLOG(WARNING) << "Could not find asset: " << asset_name;
return false;
return nullptr;
}
// |blink::AssetResolver|

View File

@@ -26,8 +26,8 @@ class AssetManager final : public AssetResolver,
bool IsValid() const override;
// |blink::AssetResolver|
bool GetAsBuffer(const std::string& asset_name,
std::vector<uint8_t>* data) const override;
std::unique_ptr<fml::Mapping> GetAsMapping(
const std::string& asset_name) const override;
private:
std::deque<std::unique_ptr<AssetResolver>> resolvers_;

View File

@@ -9,6 +9,7 @@
#include <vector>
#include "flutter/fml/macros.h"
#include "flutter/fml/mapping.h"
namespace blink {
@@ -20,8 +21,9 @@ class AssetResolver {
virtual bool IsValid() const = 0;
virtual bool GetAsBuffer(const std::string& asset_name,
std::vector<uint8_t>* data) const = 0;
FML_WARN_UNUSED_RESULT
virtual std::unique_ptr<fml::Mapping> GetAsMapping(
const std::string& asset_name) const = 0;
private:
FML_DISALLOW_COPY_AND_ASSIGN(AssetResolver);

View File

@@ -28,29 +28,23 @@ bool DirectoryAssetBundle::IsValid() const {
}
// |blink::AssetResolver|
bool DirectoryAssetBundle::GetAsBuffer(const std::string& asset_name,
std::vector<uint8_t>* data) const {
if (data == nullptr) {
return false;
}
std::unique_ptr<fml::Mapping> DirectoryAssetBundle::GetAsMapping(
const std::string& asset_name) const {
if (!is_valid_) {
FML_DLOG(WARNING) << "Asset bundle was not valid.";
return false;
return nullptr;
}
fml::FileMapping mapping(
auto mapping = std::make_unique<fml::FileMapping>(
fml::OpenFile(descriptor_, asset_name.c_str(), fml::OpenPermission::kRead,
false /* directory */),
false /* executable */);
if (mapping.GetMapping() == nullptr) {
return false;
if (mapping->GetMapping() == nullptr) {
return nullptr;
}
data->resize(mapping.GetSize());
memmove(data->data(), mapping.GetMapping(), mapping.GetSize());
return true;
return mapping;
}
} // namespace blink

View File

@@ -26,8 +26,8 @@ class DirectoryAssetBundle : public AssetResolver {
bool IsValid() const override;
// |blink::AssetResolver|
bool GetAsBuffer(const std::string& asset_name,
std::vector<uint8_t>* data) const override;
std::unique_ptr<fml::Mapping> GetAsMapping(
const std::string& asset_name) const override;
FML_DISALLOW_COPY_AND_ASSIGN(DirectoryAssetBundle);
};

View File

@@ -35,19 +35,19 @@ bool ZipAssetStore::IsValid() const {
}
// |blink::AssetResolver|
bool ZipAssetStore::GetAsBuffer(const std::string& asset_name,
std::vector<uint8_t>* data) const {
TRACE_EVENT0("flutter", "ZipAssetStore::GetAsBuffer");
std::unique_ptr<fml::Mapping> ZipAssetStore::GetAsMapping(
const std::string& asset_name) const {
TRACE_EVENT0("flutter", "ZipAssetStore::GetAsMapping");
auto found = stat_cache_.find(asset_name);
if (found == stat_cache_.end()) {
return false;
return nullptr;
}
auto unzipper = CreateUnzipper();
if (!unzipper.is_valid()) {
return false;
return nullptr;
}
int result = UNZ_OK;
@@ -55,27 +55,27 @@ bool ZipAssetStore::GetAsBuffer(const std::string& asset_name,
result = unzGoToFilePos(unzipper.get(), &(found->second.file_pos));
if (result != UNZ_OK) {
FXL_LOG(WARNING) << "unzGetCurrentFileInfo failed, error=" << result;
return false;
return nullptr;
}
result = unzOpenCurrentFile(unzipper.get());
if (result != UNZ_OK) {
FXL_LOG(WARNING) << "unzOpenCurrentFile failed, error=" << result;
return false;
return nullptr;
}
data->resize(found->second.uncompressed_size);
std::vector<uint8_t> data(found->second.uncompressed_size);
int total_read = 0;
while (total_read < static_cast<int>(data->size())) {
while (total_read < static_cast<int>(data.size())) {
int bytes_read = unzReadCurrentFile(
unzipper.get(), data->data() + total_read, data->size() - total_read);
unzipper.get(), data.data() + total_read, data.size() - total_read);
if (bytes_read <= 0) {
return false;
return nullptr;
}
total_read += bytes_read;
}
return true;
return std::make_unique<fml::DataMapping>(std::move(data));
}
void ZipAssetStore::BuildStatCache() {

View File

@@ -36,8 +36,8 @@ class ZipAssetStore final : public AssetResolver {
bool IsValid() const override;
// |blink::AssetResolver|
bool GetAsBuffer(const std::string& asset_name,
std::vector<uint8_t>* data) const override;
std::unique_ptr<fml::Mapping> GetAsMapping(
const std::string& asset_name) const override;
void BuildStatCache();

View File

@@ -14,8 +14,8 @@ namespace blink {
namespace {
void VectorReleaseProc(const void* ptr, void* context) {
delete reinterpret_cast<std::vector<uint8_t>*>(context);
void MappingReleaseProc(const void* ptr, void* context) {
delete reinterpret_cast<fml::Mapping*>(context);
}
} // anonymous namespace
@@ -90,15 +90,16 @@ SkTypeface* AssetManagerFontStyleSet::createTypeface(int i) {
TypefaceAsset& asset = assets_[index];
if (!asset.typeface) {
std::unique_ptr<std::vector<uint8_t>> asset_buf =
std::make_unique<std::vector<uint8_t>>();
if (!asset_manager_->GetAsBuffer(asset.asset, asset_buf.get()))
std::unique_ptr<fml::Mapping> asset_mapping =
asset_manager_->GetAsMapping(asset.asset);
if (asset_mapping == nullptr) {
return nullptr;
}
std::vector<uint8_t>* asset_buf_ptr = asset_buf.release();
sk_sp<SkData> asset_data =
SkData::MakeWithProc(asset_buf_ptr->data(), asset_buf_ptr->size(),
VectorReleaseProc, asset_buf_ptr);
fml::Mapping* asset_mapping_ptr = asset_mapping.release();
sk_sp<SkData> asset_data = SkData::MakeWithProc(
asset_mapping_ptr->GetMapping(), asset_mapping_ptr->GetSize(),
MappingReleaseProc, asset_mapping_ptr);
std::unique_ptr<SkMemoryStream> stream = SkMemoryStream::Make(asset_data);
// Ownership of the stream is transferred.

View File

@@ -31,19 +31,18 @@ std::shared_ptr<txt::FontCollection> FontCollection::GetFontCollection() const {
}
void FontCollection::RegisterFonts(fml::RefPtr<AssetManager> asset_manager) {
std::vector<uint8_t> manifest_data;
if (!asset_manager->GetAsBuffer("FontManifest.json", &manifest_data)) {
std::unique_ptr<fml::Mapping> manifest_mapping =
asset_manager->GetAsMapping("FontManifest.json");
if (manifest_mapping == nullptr) {
FXL_DLOG(WARNING) << "Could not find the font manifest in the asset store.";
return;
}
rapidjson::Document document;
static_assert(sizeof(decltype(manifest_data)::value_type) ==
sizeof(decltype(document)::Ch),
"");
document.Parse(
reinterpret_cast<decltype(document)::Ch*>(manifest_data.data()),
manifest_data.size());
static_assert(sizeof(decltype(document)::Ch) == sizeof(uint8_t), "");
document.Parse(reinterpret_cast<const decltype(document)::Ch*>(
manifest_mapping->GetMapping()),
manifest_mapping->GetSize());
if (document.HasParseError()) {
FXL_DLOG(WARNING) << "Error parsing the font manifest in the asset store.";
@@ -82,8 +81,8 @@ void FontCollection::RegisterFonts(fml::RefPtr<AssetManager> asset_manager) {
}
// TODO: Handle weights and styles.
font_provider->RegisterAsset(
family_name->value.GetString(), font_asset->value.GetString());
font_provider->RegisterAsset(family_name->value.GetString(),
font_asset->value.GetString());
}
}

View File

@@ -7,6 +7,7 @@
#include <vector>
#include "flutter/fml/mapping.h"
#include "lib/fxl/memory/ref_counted.h"
#include "lib/fxl/memory/ref_ptr.h"
@@ -18,7 +19,7 @@ class PlatformMessageResponse
public:
// Callable on any thread.
virtual void Complete(std::vector<uint8_t> data) = 0;
virtual void Complete(std::unique_ptr<fml::Mapping> data) = 0;
virtual void CompleteEmpty() = 0;
bool is_complete() const { return is_complete_; }

View File

@@ -39,6 +39,12 @@ Dart_Handle WrapByteData(std::vector<uint8_t> data) {
}
}
Dart_Handle WrapByteData(std::unique_ptr<fml::Mapping> mapping) {
std::vector<uint8_t> data(mapping->GetSize());
memcpy(data.data(), mapping->GetMapping(), mapping->GetSize());
return WrapByteData(std::move(data));
}
} // anonymous namespace
PlatformMessageResponseDart::PlatformMessageResponseDart(
@@ -56,7 +62,7 @@ PlatformMessageResponseDart::~PlatformMessageResponseDart() {
}
}
void PlatformMessageResponseDart::Complete(std::vector<uint8_t> data) {
void PlatformMessageResponseDart::Complete(std::unique_ptr<fml::Mapping> data) {
if (callback_.is_empty())
return;
FXL_DCHECK(!is_complete_);

View File

@@ -16,7 +16,7 @@ class PlatformMessageResponseDart : public PlatformMessageResponse {
public:
// Callable on any thread.
void Complete(std::vector<uint8_t> data) override;
void Complete(std::unique_ptr<fml::Mapping> data) override;
void CompleteEmpty() override;
protected:

View File

@@ -98,6 +98,7 @@ void RespondToPlatformMessage(Dart_Handle window,
UIDartState::Current()->window()->CompletePlatformMessageEmptyResponse(
response_id);
} else {
// TODO(engine): Avoid this copy.
const uint8_t* buffer = static_cast<const uint8_t*>(data.data());
UIDartState::Current()->window()->CompletePlatformMessageResponse(
response_id,
@@ -288,7 +289,7 @@ void Window::CompletePlatformMessageResponse(int response_id,
return;
auto response = std::move(it->second);
pending_responses_.erase(it);
response->Complete(std::move(data));
response->Complete(std::make_unique<fml::DataMapping>(std::move(data)));
}
void Window::RegisterNatives(tonic::DartLibraryNatives* natives) {

View File

@@ -391,12 +391,16 @@ void Engine::HandleAssetPlatformMessage(
std::string asset_name(reinterpret_cast<const char*>(data.data()),
data.size());
std::vector<uint8_t> asset_data;
if (asset_manager_ && asset_manager_->GetAsBuffer(asset_name, &asset_data)) {
response->Complete(std::move(asset_data));
} else {
response->CompleteEmpty();
if (asset_manager_) {
std::unique_ptr<fml::Mapping> asset_mapping =
asset_manager_->GetAsMapping(asset_name);
if (asset_mapping) {
response->Complete(std::move(asset_mapping));
return;
}
}
response->CompleteEmpty();
}
} // namespace shell

View File

@@ -135,60 +135,56 @@ std::unique_ptr<IsolateConfiguration> IsolateConfiguration::InferFromSettings(
}
// Running from kernel snapshot.
{
// TODO(engine): Add AssetManager::GetAsMapping or such to avoid the copy.
std::vector<uint8_t> kernel;
if (asset_manager && asset_manager->GetAsBuffer(
settings.application_kernel_asset, &kernel)) {
return CreateForSnapshot(
std::make_unique<fml::DataMapping>(std::move(kernel)));
if (asset_manager) {
std::unique_ptr<fml::Mapping> kernel =
asset_manager->GetAsMapping(settings.application_kernel_asset);
if (kernel) {
return CreateForSnapshot(std::move(kernel));
}
}
// Running from script snapshot.
{
// TODO(engine): Add AssetManager::GetAsMapping or such to avoid the copy.
std::vector<uint8_t> script_snapshot;
if (asset_manager && asset_manager->GetAsBuffer(
settings.script_snapshot_path, &script_snapshot)) {
return CreateForSnapshot(
std::make_unique<fml::DataMapping>(std::move(script_snapshot)));
if (asset_manager) {
std::unique_ptr<fml::Mapping> script_snapshot =
asset_manager->GetAsMapping(settings.script_snapshot_path);
if (script_snapshot) {
return CreateForSnapshot(std::move(script_snapshot));
}
}
// Running from kernel divided into several pieces (for sharing).
{
// TODO(fuchsia): Add AssetManager::GetAsMapping or such to avoid the copy.
// TODO(fuchsia): Use async blobfs API once it becomes available.
std::vector<uint8_t> kernel_list;
if (asset_manager &&
asset_manager->GetAsBuffer(settings.application_kernel_list_asset,
&kernel_list)) {
// TODO(fuchsia): Use async blobfs API once it becomes available.
if (asset_manager) {
std::unique_ptr<fml::Mapping> kernel_list =
asset_manager->GetAsMapping(settings.application_kernel_list_asset);
if (kernel_list) {
const char* kernel_list_str =
reinterpret_cast<const char*>(kernel_list->GetMapping());
size_t kernel_list_size = kernel_list->GetSize();
std::vector<std::unique_ptr<fml::Mapping>> kernel_pieces;
size_t piece_path_start = 0;
while (piece_path_start < kernel_list.size()) {
while (piece_path_start < kernel_list_size) {
size_t piece_path_end = piece_path_start;
while ((piece_path_end < kernel_list.size()) &&
(kernel_list[piece_path_end] != '\n')) {
while ((piece_path_end < kernel_list_size) &&
(kernel_list_str[piece_path_end] != '\n')) {
piece_path_end++;
}
std::string piece_path(
reinterpret_cast<const char*>(&kernel_list[piece_path_start]),
piece_path_end - piece_path_start);
std::vector<uint8_t> piece;
if (!asset_manager->GetAsBuffer(piece_path, &piece)) {
std::string piece_path(&kernel_list_str[piece_path_start],
piece_path_end - piece_path_start);
std::unique_ptr<fml::Mapping> piece =
asset_manager->GetAsMapping(piece_path);
if (piece == nullptr) {
FXL_LOG(ERROR) << "Failed to load: " << piece_path;
return nullptr;
}
kernel_pieces.emplace_back(
std::make_unique<fml::DataMapping>(std::move(piece)));
kernel_pieces.emplace_back(std::move(piece));
piece_path_start = piece_path_end + 1;
}
return CreateForKernelList(std::move(kernel_pieces));
}
}

View File

@@ -21,28 +21,35 @@ bool APKAssetProvider::IsValid() const {
return true;
}
bool APKAssetProvider::GetAsBuffer(const std::string& asset_name,
std::vector<uint8_t>* data) const {
class APKAssetMapping : public fml::Mapping {
public:
APKAssetMapping(AAsset* asset) : asset_(asset) {}
~APKAssetMapping() override { AAsset_close(asset_); }
size_t GetSize() const override { return AAsset_getLength(asset_); }
const uint8_t* GetMapping() const override {
return reinterpret_cast<const uint8_t*>(AAsset_getBuffer(asset_));
}
private:
AAsset* const asset_;
FML_DISALLOW_COPY_AND_ASSIGN(APKAssetMapping);
};
std::unique_ptr<fml::Mapping> APKAssetProvider::GetAsMapping(
const std::string& asset_name) const {
std::stringstream ss;
ss << directory_.c_str() << "/" << asset_name;
AAsset* asset =
AAssetManager_open(assetManager_, ss.str().c_str(), AASSET_MODE_BUFFER);
if (!asset) {
return false;
return nullptr;
}
uint8_t* buffer = (uint8_t*)AAsset_getBuffer(asset);
if (!buffer) {
FXL_LOG(ERROR) << "Got null trying to acquire buffer for asset:" << asset;
AAsset_close(asset);
return false;
}
data->resize(AAsset_getLength(asset));
std::copy(buffer, buffer + data->size(), data->begin());
AAsset_close(asset);
return true;
return std::make_unique<APKAssetMapping>(asset);
}
} // namespace blink

View File

@@ -30,8 +30,8 @@ class APKAssetProvider final : public AssetResolver {
bool IsValid() const override;
// |blink::AssetResolver|
virtual bool GetAsBuffer(const std::string& asset_name,
std::vector<uint8_t>* data) const override;
std::unique_ptr<fml::Mapping> GetAsMapping(
const std::string& asset_name) const override;
FXL_DISALLOW_COPY_AND_ASSIGN(APKAssetProvider);
};

View File

@@ -18,7 +18,8 @@ PlatformMessageResponseAndroid::PlatformMessageResponseAndroid(
platform_task_runner_(std::move(platform_task_runner)) {}
// |blink::PlatformMessageResponse|
void PlatformMessageResponseAndroid::Complete(std::vector<uint8_t> data) {
void PlatformMessageResponseAndroid::Complete(
std::unique_ptr<fml::Mapping> data) {
platform_task_runner_->PostTask(
fxl::MakeCopyable([response = response_id_, //
weak_java_object = weak_java_object_, //
@@ -37,9 +38,10 @@ void PlatformMessageResponseAndroid::Complete(std::vector<uint8_t> data) {
// Convert the vector to a Java byte array.
fml::jni::ScopedJavaLocalRef<jbyteArray> data_array(
env, env->NewByteArray(data.size()));
env->SetByteArrayRegion(data_array.obj(), 0, data.size(),
reinterpret_cast<const jbyte*>(data.data()));
env, env->NewByteArray(data->GetSize()));
env->SetByteArrayRegion(
data_array.obj(), 0, data->GetSize(),
reinterpret_cast<const jbyte*>(data->GetMapping()));
// Make the response call into Java.
FlutterViewHandlePlatformMessageResponse(env, java_object.obj(),
@@ -50,8 +52,8 @@ void PlatformMessageResponseAndroid::Complete(std::vector<uint8_t> data) {
// |blink::PlatformMessageResponse|
void PlatformMessageResponseAndroid::CompleteEmpty() {
platform_task_runner_->PostTask(
fxl::MakeCopyable([response = response_id_, //
weak_java_object = weak_java_object_ //
fxl::MakeCopyable([response = response_id_, //
weak_java_object = weak_java_object_ //
]() {
// We are on the platform thread. Attempt to get the strong reference to
// the Java object.

View File

@@ -15,7 +15,7 @@ namespace shell {
class PlatformMessageResponseAndroid : public blink::PlatformMessageResponse {
public:
// |blink::PlatformMessageResponse|
void Complete(std::vector<uint8_t> data) override;
void Complete(std::unique_ptr<fml::Mapping> data) override;
// |blink::PlatformMessageResponse|
void CompleteEmpty() override;

View File

@@ -106,7 +106,8 @@ void PlatformViewAndroid::InvokePlatformMessageResponseCallback(
response_data, response_data + java_response_position);
auto message_response = std::move(it->second);
pending_responses_.erase(it);
message_response->Complete(std::move(response));
message_response->Complete(
std::make_unique<fml::DataMapping>(std::move(response)));
}
void PlatformViewAndroid::InvokePlatformMessageEmptyResponseCallback(
@@ -190,7 +191,8 @@ void PlatformViewAndroid::UpdateSemantics(blink::SemanticsNodeUpdates update) {
size_t num_bytes = 0;
for (const auto& value : update) {
num_bytes += kBytesPerNode;
num_bytes += value.second.childrenInTraversalOrder.size() * kBytesPerChild;
num_bytes +=
value.second.childrenInTraversalOrder.size() * kBytesPerChild;
num_bytes += value.second.childrenInHitTestOrder.size() * kBytesPerChild;
}

View File

@@ -174,10 +174,10 @@ std::unique_ptr<IsolateConfiguration> CreateIsolateConfiguration(
const auto configuration_from_blob =
[&asset_manager](const std::string& snapshot_name)
-> std::unique_ptr<IsolateConfiguration> {
std::vector<uint8_t> blob;
if (asset_manager.GetAsBuffer(snapshot_name, &blob)) {
return IsolateConfiguration::CreateForSnapshot(
std::make_unique<fml::DataMapping>(std::move(blob)));
std::unique_ptr<fml::Mapping> blob =
asset_manager.GetAsMapping(snapshot_name);
if (blob) {
return IsolateConfiguration::CreateForSnapshot(std::move(blob));
}
return nullptr;
};

View File

@@ -9,12 +9,18 @@
#include <vector>
#include "flutter/fml/mapping.h"
namespace shell {
std::vector<uint8_t> GetVectorFromNSData(NSData* data);
NSData* GetNSDataFromVector(const std::vector<uint8_t>& buffer);
std::unique_ptr<fml::Mapping> GetMappingFromNSData(NSData* data);
NSData* GetNSDataFromMapping(std::unique_ptr<fml::Mapping> mapping);
} // namespace shell
#endif // FLUTTER_SHELL_PLATFORM_DARWIN_COMMON_BUFFER_CONVERSIONS_H_

View File

@@ -15,4 +15,12 @@ NSData* GetNSDataFromVector(const std::vector<uint8_t>& buffer) {
return [NSData dataWithBytes:buffer.data() length:buffer.size()];
}
std::unique_ptr<fml::Mapping> GetMappingFromNSData(NSData* data) {
return std::make_unique<fml::DataMapping>(GetVectorFromNSData(data));
}
NSData* GetNSDataFromMapping(std::unique_ptr<fml::Mapping> mapping) {
return [NSData dataWithBytes:mapping->GetMapping() length:mapping->GetSize()];
}
} // namespace shell

View File

@@ -20,10 +20,10 @@ namespace shell {
class PlatformMessageResponseDarwin : public blink::PlatformMessageResponse {
public:
void Complete(std::vector<uint8_t> data) override {
void Complete(std::unique_ptr<fml::Mapping> data) override {
fxl::RefPtr<PlatformMessageResponseDarwin> self(this);
platform_task_runner_->PostTask(fxl::MakeCopyable([self, data = std::move(data)]() mutable {
self->callback_.get()(shell::GetNSDataFromVector(data));
self->callback_.get()(shell::GetNSDataFromMapping(std::move(data)));
}));
}

View File

@@ -27,7 +27,7 @@ void PlatformMessageRouter::HandlePlatformMessage(
handler(data, ^(NSData* reply) {
if (completer) {
if (reply) {
completer->Complete(GetVectorFromNSData(reply));
completer->Complete(GetMappingFromNSData(reply));
} else {
completer->CompleteEmpty();
}

View File

@@ -360,7 +360,8 @@ FlutterResult FlutterEngineSendPlatformMessageResponse(
if (data_length == 0) {
response->CompleteEmpty();
} else {
response->Complete({data, data + data_length});
response->Complete(std::make_unique<fml::DataMapping>(
std::vector<uint8_t>({data, data + data_length})));
}
delete handle;