mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Add support for snapshot loading to Sky
This CL adds the ability to load Dart snapshot files created by sky_packager in Sky. Using a snapshot lets us transmit all the code for an app in a single blob and should improve startup time. Later CLs will make this codepath easier to use and evaluate performance. R=eseidel@chromium.org Review URL: https://codereview.chromium.org/1197133004.
This commit is contained in:
parent
c89c751937
commit
1f258f383e
@ -1058,6 +1058,8 @@ sky_core_files = [
|
||||
"script/dart_loader.h",
|
||||
"script/dart_service_isolate.cc",
|
||||
"script/dart_service_isolate.h",
|
||||
"script/dart_snapshot_loader.cc",
|
||||
"script/dart_snapshot_loader.h",
|
||||
"script/dom_dart_state.cc",
|
||||
"script/dom_dart_state.h",
|
||||
"script/monitor.h",
|
||||
|
||||
@ -27,6 +27,7 @@
|
||||
#include "sky/engine/core/script/dart_dependency_catcher.h"
|
||||
#include "sky/engine/core/script/dart_loader.h"
|
||||
#include "sky/engine/core/script/dart_service_isolate.h"
|
||||
#include "sky/engine/core/script/dart_snapshot_loader.h"
|
||||
#include "sky/engine/core/script/dom_dart_state.h"
|
||||
#include "sky/engine/public/platform/Platform.h"
|
||||
#include "sky/engine/tonic/dart_api_scope.h"
|
||||
@ -40,6 +41,16 @@
|
||||
#include "sky/engine/wtf/text/TextPosition.h"
|
||||
|
||||
namespace blink {
|
||||
namespace {
|
||||
|
||||
void CreateEmptyRootLibraryIfNeeded() {
|
||||
if (Dart_IsNull(Dart_RootLibrary())) {
|
||||
Dart_LoadScript(Dart_NewStringFromCString("dart:empty"), Dart_EmptyString(),
|
||||
0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#if ENABLE(DART_STRICT)
|
||||
static const char* kCheckedModeArgs[] = {"--enable_asserts",
|
||||
@ -126,6 +137,9 @@ void DartController::DidLoadMainLibrary(KURL url) {
|
||||
}
|
||||
|
||||
void DartController::LoadMainLibrary(const KURL& url, mojo::URLResponsePtr response) {
|
||||
DartState::Scope scope(dart_state());
|
||||
CreateEmptyRootLibraryIfNeeded();
|
||||
|
||||
DartLoader& loader = dart_state()->loader();
|
||||
DartDependencyCatcher dependency_catcher(loader);
|
||||
loader.LoadLibrary(url, response.Pass());
|
||||
@ -133,13 +147,33 @@ void DartController::LoadMainLibrary(const KURL& url, mojo::URLResponsePtr respo
|
||||
base::Bind(&DartController::DidLoadMainLibrary, weak_factory_.GetWeakPtr(), url));
|
||||
}
|
||||
|
||||
void DartController::DidLoadSnapshot() {
|
||||
DCHECK(Dart_CurrentIsolate() == nullptr);
|
||||
snapshot_loader_ = nullptr;
|
||||
|
||||
Dart_Isolate isolate = dart_state()->isolate();
|
||||
DartIsolateScope isolate_scope(isolate);
|
||||
DartApiScope dart_api_scope;
|
||||
|
||||
Dart_Handle library = Dart_RootLibrary();
|
||||
if (LogIfError(library))
|
||||
return;
|
||||
DartInvokeAppField(library, ToDart("main"), 0, nullptr);
|
||||
}
|
||||
|
||||
void DartController::LoadSnapshot(const KURL& url, mojo::URLResponsePtr response) {
|
||||
snapshot_loader_ = adoptPtr(new DartSnapshotLoader(dart_state()));
|
||||
snapshot_loader_->LoadSnapshot(url, response.Pass(),
|
||||
base::Bind(&DartController::DidLoadSnapshot, weak_factory_.GetWeakPtr()));
|
||||
}
|
||||
|
||||
void DartController::LoadScriptInModule(
|
||||
AbstractModule* module,
|
||||
const String& source,
|
||||
const TextPosition& position,
|
||||
const LoadFinishedCallback& finished_callback) {
|
||||
DartIsolateScope isolate_scope(dart_state()->isolate());
|
||||
DartApiScope dart_api_scope;
|
||||
DartState::Scope scope(dart_state());
|
||||
CreateEmptyRootLibraryIfNeeded();
|
||||
|
||||
DartDependencyCatcher dependency_catcher(dart_state()->loader());
|
||||
Dart_Handle library_handle = CreateLibrary(module, source, position);
|
||||
@ -274,6 +308,7 @@ static Dart_Isolate IsolateCreateCallback(const char* script_uri,
|
||||
|
||||
// Create & start the handle watcher isolate
|
||||
CHECK(kDartIsolateSnapshotBuffer);
|
||||
// TODO(abarth): Who deletes this DartState instance?
|
||||
DartState* dart_state = new DartState();
|
||||
Dart_Isolate isolate =
|
||||
Dart_CreateIsolate("sky:handle_watcher", "", kDartIsolateSnapshotBuffer,
|
||||
@ -289,9 +324,8 @@ static Dart_Isolate IsolateCreateCallback(const char* script_uri,
|
||||
Builtin::SetNativeResolver(Builtin::kMojoInternalLibrary);
|
||||
Builtin::SetNativeResolver(Builtin::kIOLibrary);
|
||||
|
||||
// Ensure the isolate has a root library.
|
||||
Dart_LoadScript(Dart_NewStringFromCString("dart:empty"),
|
||||
Dart_NewStringFromCString(""), 0, 0);
|
||||
if (!script_uri)
|
||||
CreateEmptyRootLibraryIfNeeded();
|
||||
}
|
||||
|
||||
Dart_ExitIsolate();
|
||||
@ -334,10 +368,6 @@ void DartController::CreateIsolateFor(PassOwnPtr<DOMDartState> state) {
|
||||
{
|
||||
DartApiScope apiScope;
|
||||
|
||||
// Ensure the isolate has a root library.
|
||||
Dart_LoadScript(Dart_NewStringFromCString("dart:empty"),
|
||||
Dart_NewStringFromCString(""), 0, 0);
|
||||
|
||||
Builtin::SetNativeResolver(Builtin::kBuiltinLibrary);
|
||||
Builtin::SetNativeResolver(Builtin::kMojoInternalLibrary);
|
||||
Builtin::SetNativeResolver(Builtin::kIOLibrary);
|
||||
|
||||
@ -18,6 +18,7 @@ namespace blink {
|
||||
class AbstractModule;
|
||||
class BuiltinSky;
|
||||
class DOMDartState;
|
||||
class DartSnapshotLoader;
|
||||
class DartValue;
|
||||
class HTMLScriptElement;
|
||||
class KURL;
|
||||
@ -35,6 +36,7 @@ class DartController {
|
||||
|
||||
// Can either issue the url load ourselves or take an existing response:
|
||||
void LoadMainLibrary(const KURL& url, mojo::URLResponsePtr response = nullptr);
|
||||
void LoadSnapshot(const KURL& url, mojo::URLResponsePtr response = nullptr);
|
||||
|
||||
void LoadScriptInModule(AbstractModule* module,
|
||||
const String& source,
|
||||
@ -57,9 +59,11 @@ class DartController {
|
||||
const TextPosition& position);
|
||||
|
||||
void DidLoadMainLibrary(KURL url);
|
||||
void DidLoadSnapshot();
|
||||
|
||||
OwnPtr<DOMDartState> dom_dart_state_;
|
||||
OwnPtr<BuiltinSky> builtin_sky_;
|
||||
OwnPtr<DartSnapshotLoader> snapshot_loader_;
|
||||
|
||||
base::WeakPtrFactory<DartController> weak_factory_;
|
||||
|
||||
|
||||
66
engine/core/script/dart_snapshot_loader.cc
Normal file
66
engine/core/script/dart_snapshot_loader.cc
Normal file
@ -0,0 +1,66 @@
|
||||
// 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 "sky/engine/config.h"
|
||||
#include "sky/engine/core/script/dart_snapshot_loader.h"
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "base/trace_event/trace_event.h"
|
||||
#include "sky/engine/platform/weborigin/KURL.h"
|
||||
#include "sky/engine/tonic/dart_api_scope.h"
|
||||
#include "sky/engine/tonic/dart_converter.h"
|
||||
#include "sky/engine/tonic/dart_error.h"
|
||||
#include "sky/engine/tonic/dart_isolate_scope.h"
|
||||
#include "sky/engine/wtf/MainThread.h"
|
||||
|
||||
using mojo::common::DataPipeDrainer;
|
||||
|
||||
namespace blink {
|
||||
|
||||
DartSnapshotLoader::DartSnapshotLoader(DartState* dart_state)
|
||||
: dart_state_(dart_state->GetWeakPtr()) {
|
||||
}
|
||||
|
||||
DartSnapshotLoader::~DartSnapshotLoader() {
|
||||
}
|
||||
|
||||
void DartSnapshotLoader::LoadSnapshot(const KURL& url,
|
||||
mojo::URLResponsePtr response,
|
||||
const base::Closure& callback) {
|
||||
TRACE_EVENT_ASYNC_BEGIN0("sky", "DartSnapshotLoader::LoadSnapshot", this);
|
||||
callback_ = callback;
|
||||
|
||||
if (!response) {
|
||||
fetcher_ = adoptPtr(new MojoFetcher(this, url));
|
||||
} else {
|
||||
OnReceivedResponse(response.Pass());
|
||||
}
|
||||
}
|
||||
|
||||
void DartSnapshotLoader::OnReceivedResponse(mojo::URLResponsePtr response) {
|
||||
if (response->status_code != 200) {
|
||||
callback_.Run();
|
||||
return;
|
||||
}
|
||||
drainer_ = adoptPtr(new DataPipeDrainer(this, response->body.Pass()));
|
||||
}
|
||||
|
||||
void DartSnapshotLoader::OnDataAvailable(const void* data, size_t num_bytes) {
|
||||
buffer_.append(static_cast<const uint8_t*>(data), num_bytes);
|
||||
}
|
||||
|
||||
void DartSnapshotLoader::OnDataComplete() {
|
||||
TRACE_EVENT_ASYNC_END0("sky", "DartSnapshotLoader::LoadSnapshot", this);
|
||||
|
||||
{
|
||||
DartIsolateScope scope(dart_state_->isolate());
|
||||
DartApiScope api_scope;
|
||||
|
||||
LogIfError(Dart_LoadScriptFromSnapshot(buffer_.data(), buffer_.size()));
|
||||
}
|
||||
|
||||
callback_.Run();
|
||||
}
|
||||
|
||||
} // namespace blink
|
||||
55
engine/core/script/dart_snapshot_loader.h
Normal file
55
engine/core/script/dart_snapshot_loader.h
Normal file
@ -0,0 +1,55 @@
|
||||
// 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.
|
||||
|
||||
#ifndef SKY_ENGINE_CORE_SCRIPT_DART_SNAPSHOT_LOADER_H_
|
||||
#define SKY_ENGINE_CORE_SCRIPT_DART_SNAPSHOT_LOADER_H_
|
||||
|
||||
#include "base/callback_forward.h"
|
||||
#include "base/macros.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "dart/runtime/include/dart_api.h"
|
||||
#include "mojo/common/data_pipe_drainer.h"
|
||||
#include "mojo/services/network/public/interfaces/url_loader.mojom.h"
|
||||
#include "sky/engine/platform/fetcher/MojoFetcher.h"
|
||||
#include "sky/engine/wtf/OwnPtr.h"
|
||||
#include "sky/engine/wtf/Vector.h"
|
||||
#include "sky/engine/wtf/text/WTFString.h"
|
||||
|
||||
namespace blink {
|
||||
|
||||
class DartState;
|
||||
class KURL;
|
||||
|
||||
class DartSnapshotLoader : public MojoFetcher::Client,
|
||||
public mojo::common::DataPipeDrainer::Client {
|
||||
public:
|
||||
explicit DartSnapshotLoader(DartState* dart_state);
|
||||
~DartSnapshotLoader();
|
||||
|
||||
void LoadSnapshot(const KURL& url, mojo::URLResponsePtr response,
|
||||
const base::Closure& callback);
|
||||
|
||||
DartState* dart_state() const { return dart_state_.get(); }
|
||||
|
||||
private:
|
||||
// MojoFetcher::Client
|
||||
void OnReceivedResponse(mojo::URLResponsePtr response) override;
|
||||
|
||||
// mojo::common::DataPipeDrainer::Client
|
||||
void OnDataAvailable(const void* data, size_t num_bytes) override;
|
||||
void OnDataComplete() override;
|
||||
|
||||
base::WeakPtr<DartState> dart_state_;
|
||||
// TODO(abarth): Should we be using SharedBuffer to buffer the data?
|
||||
Vector<uint8_t> buffer_;
|
||||
OwnPtr<MojoFetcher> fetcher_;
|
||||
OwnPtr<mojo::common::DataPipeDrainer> drainer_;
|
||||
base::Closure callback_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(DartSnapshotLoader);
|
||||
};
|
||||
|
||||
} // namespace blink
|
||||
|
||||
#endif // SKY_ENGINE_CORE_SCRIPT_DART_SNAPSHOT_LOADER_H_
|
||||
@ -47,7 +47,9 @@ void SkyView::SetDisplayMetrics(const SkyDisplayMetrics& metrics) {
|
||||
data_->view_->setDisplayMetrics(display_metrics_);
|
||||
}
|
||||
|
||||
void SkyView::Load(const WebURL& url, mojo::URLResponsePtr response) {
|
||||
void SkyView::Load(const WebURL& web_url, mojo::URLResponsePtr response) {
|
||||
KURL url = web_url;
|
||||
|
||||
data_->view_ = View::create(base::Bind(
|
||||
&SkyView::ScheduleFrame, weak_factory_.GetWeakPtr()));
|
||||
data_->view_->setDisplayMetrics(display_metrics_);
|
||||
@ -63,7 +65,10 @@ void SkyView::Load(const WebURL& url, mojo::URLResponsePtr response) {
|
||||
client_->DidCreateIsolate(isolate);
|
||||
}
|
||||
|
||||
dart_controller_->LoadMainLibrary(url, response.Pass());
|
||||
if (url.path().endsWith(".snapshot"))
|
||||
dart_controller_->LoadSnapshot(url, response.Pass());
|
||||
else
|
||||
dart_controller_->LoadMainLibrary(url, response.Pass());
|
||||
}
|
||||
|
||||
void SkyView::BeginFrame(base::TimeTicks frame_time) {
|
||||
|
||||
@ -104,7 +104,8 @@ bool WebView::shouldUseWebView(const GURL& url)
|
||||
filename.resize(queryStart);
|
||||
// For now .dart indicates we should use SkyView. Eventually we'll
|
||||
// use SkyView for all urls regardless of file extension.
|
||||
return !EndsWith(filename, ".dart", false);
|
||||
return !EndsWith(filename, ".dart", false)
|
||||
&& !EndsWith(filename, ".snapshot", false);
|
||||
}
|
||||
|
||||
WebView* WebView::create(WebViewClient* client)
|
||||
|
||||
@ -15,9 +15,6 @@
|
||||
|
||||
namespace {
|
||||
|
||||
static const char kSkyInternalsLibraryName[] = "dart:sky.internals";
|
||||
static const char kSkyInternalsURL[] = "package:sky/internals.dart";
|
||||
|
||||
std::string Fetch(const std::string& url) {
|
||||
base::FilePath path(url);
|
||||
std::string source;
|
||||
@ -122,14 +119,6 @@ Dart_Handle HandleLibraryTag(Dart_LibraryTag tag,
|
||||
return Dart_NewApiError("Unknown library tag.");
|
||||
}
|
||||
|
||||
void LoadSkyInternals() {
|
||||
DartApiScope api_scope;
|
||||
|
||||
Dart_Handle library_name = StringToDart(kSkyInternalsLibraryName);
|
||||
std::string url = GetLoader().CanonicalizePackageURL(kSkyInternalsURL);
|
||||
LogIfError(Dart_LoadLibrary(library_name, StringToDart(Fetch(url)), 0, 0));
|
||||
}
|
||||
|
||||
void LoadScript(const std::string& url) {
|
||||
LogIfError(
|
||||
Dart_LoadScript(StringToDart(url), StringToDart(Fetch(url)), 0, 0));
|
||||
|
||||
@ -12,7 +12,6 @@
|
||||
Dart_Handle HandleLibraryTag(Dart_LibraryTag tag,
|
||||
Dart_Handle library,
|
||||
Dart_Handle url);
|
||||
void LoadSkyInternals();
|
||||
void LoadScript(const std::string& url);
|
||||
|
||||
#endif // SKY_TOOLS_PACKAGER_LOADER_H_
|
||||
|
||||
@ -32,7 +32,6 @@ Dart_Isolate CreateDartIsolate() {
|
||||
|
||||
CHECK(isolate) << error;
|
||||
CHECK(!LogIfError(Dart_SetLibraryTagHandler(HandleLibraryTag)));
|
||||
LoadSkyInternals();
|
||||
|
||||
Dart_ExitIsolate();
|
||||
return isolate;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user