Skip to content

Commit

Permalink
[ VM / CLI ] Run DartDev isolate from snapshot when possible
Browse files Browse the repository at this point in the history
This change tries to run from dartdev.dart.snapshot and falls back to
running from dartdev.dill if incompatible VM flags are provided.

Fixes dart-lang/sdk#43969

Performance results:

dart test.dart (no CLI isolate): 0.167s
dart run test (from snapshot):   0.208s
dart run test (from kernel):     0.326s

TEST=pkg/dartdev/test/load_from_dill_test.dart

Change-Id: I3195886b86676580ef2a0221f0284328964ef061
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/178300
Commit-Queue: Ben Konyi <bkonyi@google.com>
Reviewed-by: Siva Annamalai <asiva@google.com>
  • Loading branch information
bkonyi authored and commit-bot@chromium.org committed Jan 11, 2021
1 parent 9d1a307 commit c42c76f
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 26 deletions.
29 changes: 29 additions & 0 deletions pkg/dartdev/test/load_from_dill_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:io';

import 'package:test/test.dart';

import 'utils.dart';

void main() {
TestProject p;

tearDown(() => p?.dispose());

test("Fallback to dartdev.dill from dartdev.dart.snapshot for 'Hello World'",
() {
p = project(mainSrc: "void main() { print('Hello World'); }");
// The DartDev snapshot includes the --use-bare-instructions flag. If
// --no-use-bare-instructions is passed, the VM will fail to load the
// snapshot and should fall back to using the DartDev dill file.
ProcessResult result =
p.runSync(['--no-use-bare-instructions', 'run', p.relativeFilePath]);

expect(result.stdout, contains('Hello World'));
expect(result.stderr, isEmpty);
expect(result.exitCode, 0);
});
}
15 changes: 12 additions & 3 deletions runtime/bin/dartdev_isolate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -57,28 +57,37 @@ bool DartDevIsolate::ShouldParseCommand(const char* script_uri) {
(strncmp(script_uri, "google3://", 10) != 0));
}

Utils::CStringUniquePtr DartDevIsolate::TryResolveDartDevSnapshotPath() {
Utils::CStringUniquePtr DartDevIsolate::TryResolveArtifactPath(
const char* filename) {
// |dir_prefix| includes the last path seperator.
auto dir_prefix = EXEUtils::GetDirectoryPrefixFromExeName();

// First assume we're in dart-sdk/bin.
char* snapshot_path =
Utils::SCreate("%ssnapshots/dartdev.dill", dir_prefix.get());
Utils::SCreate("%ssnapshots/%s", dir_prefix.get(), filename);
if (File::Exists(nullptr, snapshot_path)) {
return Utils::CreateCStringUniquePtr(snapshot_path);
}
free(snapshot_path);

// If we're not in dart-sdk/bin, we might be in one of the $SDK/out/*
// directories. Try to use a snapshot from a previously built SDK.
snapshot_path = Utils::SCreate("%sdartdev.dill", dir_prefix.get());
snapshot_path = Utils::SCreate("%s%s", dir_prefix.get(), filename);
if (File::Exists(nullptr, snapshot_path)) {
return Utils::CreateCStringUniquePtr(snapshot_path);
}
free(snapshot_path);
return Utils::CreateCStringUniquePtr(nullptr);
}

Utils::CStringUniquePtr DartDevIsolate::TryResolveDartDevSnapshotPath() {
return TryResolveArtifactPath("dartdev.dart.snapshot");
}

Utils::CStringUniquePtr DartDevIsolate::TryResolveDartDevKernelPath() {
return TryResolveArtifactPath("dartdev.dill");
}

void DartDevIsolate::DartDevRunner::Run(
Dart_IsolateGroupCreateCallback create_isolate,
char** packages_file,
Expand Down
8 changes: 6 additions & 2 deletions runtime/bin/dartdev_isolate.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@ class DartDevIsolate {

static bool should_run_dart_dev() { return should_run_dart_dev_; }

// Attempts to find the DartDev snapshot. If the snapshot cannot be found,
// the VM will shutdown.
// Attempts to find the path of the DartDev kernel file.
static Utils::CStringUniquePtr TryResolveDartDevKernelPath();

// Attempts to find the path of the DartDev snapshot.
static Utils::CStringUniquePtr TryResolveDartDevSnapshotPath();

// Starts a DartDev instance in a new isolate and runs it to completion.
Expand Down Expand Up @@ -89,6 +91,8 @@ class DartDevIsolate {
};

private:
static Utils::CStringUniquePtr TryResolveArtifactPath(const char* filename);

static DartDevRunner runner_;
static bool should_run_dart_dev_;

Expand Down
76 changes: 56 additions & 20 deletions runtime/bin/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -584,40 +584,76 @@ static Dart_Isolate CreateAndSetupDartDevIsolate(const char* script_uri,
int64_t start = Dart_TimelineGetMicros();

auto dartdev_path = DartDevIsolate::TryResolveDartDevSnapshotPath();
if (dartdev_path == nullptr) {
*error = Utils::StrDup("Unable to find DartDev snapshot");
return nullptr;
}

Dart_Isolate isolate = nullptr;
const uint8_t* isolate_snapshot_data = core_isolate_snapshot_data;
const uint8_t* isolate_snapshot_instructions =
core_isolate_snapshot_instructions;
IsolateGroupData* isolate_group_data = nullptr;
IsolateData* isolate_data = nullptr;

auto isolate_group_data =
new IsolateGroupData(DART_DEV_ISOLATE_NAME, packages_config, nullptr,
/*isolate_run_app_snapshot*/ false);
uint8_t* application_kernel_buffer = NULL;
intptr_t application_kernel_buffer_size = 0;
dfe.ReadScript(dartdev_path.get(), &application_kernel_buffer,
&application_kernel_buffer_size);
isolate_group_data->SetKernelBufferNewlyOwned(application_kernel_buffer,
application_kernel_buffer_size);
AppSnapshot* app_snapshot;
bool isolate_run_app_snapshot = true;
if (dartdev_path.get() != nullptr &&
(app_snapshot = Snapshot::TryReadAppSnapshot(dartdev_path.get())) !=
nullptr) {
const uint8_t* isolate_snapshot_data = NULL;
const uint8_t* isolate_snapshot_instructions = NULL;
const uint8_t* ignore_vm_snapshot_data;
const uint8_t* ignore_vm_snapshot_instructions;
app_snapshot->SetBuffers(
&ignore_vm_snapshot_data, &ignore_vm_snapshot_instructions,
&isolate_snapshot_data, &isolate_snapshot_instructions);
isolate_group_data =
new IsolateGroupData(dartdev_path.get(), packages_config, app_snapshot,
isolate_run_app_snapshot);
isolate_data = new IsolateData(isolate_group_data);
isolate = Dart_CreateIsolateGroup(
DART_DEV_ISOLATE_NAME, DART_DEV_ISOLATE_NAME, isolate_snapshot_data,
isolate_snapshot_instructions, flags, isolate_group_data, isolate_data,
error);
}

auto isolate_data = new IsolateData(isolate_group_data);
Dart_Isolate isolate = nullptr;
isolate = Dart_CreateIsolateGroup(
DART_DEV_ISOLATE_NAME, DART_DEV_ISOLATE_NAME, isolate_snapshot_data,
isolate_snapshot_instructions, flags, isolate_group_data, isolate_data,
error);
if (isolate == nullptr) {
isolate_run_app_snapshot = false;
dartdev_path = DartDevIsolate::TryResolveDartDevKernelPath();
// Clear error from app snapshot and retry from kernel.
free(*error);
*error = nullptr;

if (app_snapshot != nullptr) {
delete app_snapshot;
}

if (dartdev_path.get() != nullptr) {
isolate_group_data =
new IsolateGroupData(DART_DEV_ISOLATE_NAME, packages_config, nullptr,
isolate_run_app_snapshot);
uint8_t* application_kernel_buffer = NULL;
intptr_t application_kernel_buffer_size = 0;
dfe.ReadScript(dartdev_path.get(), &application_kernel_buffer,
&application_kernel_buffer_size);
isolate_group_data->SetKernelBufferNewlyOwned(
application_kernel_buffer, application_kernel_buffer_size);

isolate_data = new IsolateData(isolate_group_data);
isolate = Dart_CreateIsolateGroup(
DART_DEV_ISOLATE_NAME, DART_DEV_ISOLATE_NAME, isolate_snapshot_data,
isolate_snapshot_instructions, flags, isolate_group_data,
isolate_data, error);
}
}

Dart_Isolate created_isolate = nullptr;
if (isolate == nullptr) {
Syslog::PrintErr("Failed to start the Dart CLI isolate\n");
delete isolate_data;
delete isolate_group_data;
return nullptr;
} else {
created_isolate = IsolateSetupHelper(
isolate, false, DART_DEV_ISOLATE_NAME, packages_config,
/*isolate_run_app_snapshot*/ false, flags, error, exit_code);
isolate_run_app_snapshot, flags, error, exit_code);
}
int64_t end = Dart_TimelineGetMicros();
Dart_TimelineEvent("CreateAndSetupDartDevIsolate", start, end,
Expand Down
9 changes: 9 additions & 0 deletions sdk/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ declare_args() {
# ........dart2js.dart.snapshot
# ........dart2native.dart.snapshot (if not on ia32)
# ........dartanalyzer.dart.snapshot
# ........dartdev.dart.snapshot
# ........dartdev.dill
# ........dartdevc.dart.snapshot
# ........dartdoc.dart.snapshot
Expand Down Expand Up @@ -117,6 +118,10 @@ _platform_sdk_snapshots = [
"dartanalyzer",
"../utils/dartanalyzer:generate_dartanalyzer_snapshot",
],
[
"dartdev",
"../utils/dartdev:dartdev",
],
[
"dartdoc",
"../utils/dartdoc",
Expand Down Expand Up @@ -162,6 +167,10 @@ _full_sdk_snapshots = [
"dartanalyzer",
"../utils/dartanalyzer:generate_dartanalyzer_snapshot",
],
[
"dartdev",
"../utils/dartdev:generate_dartdev_snapshot",
],
[
"dartdevc",
"../utils/dartdevc",
Expand Down
20 changes: 19 additions & 1 deletion utils/dartdev/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ dartdev_files = exec_script("../../tools/list_dart_files.py",
"list lines")

group("dartdev") {
public_deps = [ ":copy_dartdev_kernel" ]
public_deps = [
":copy_dartdev_kernel",
":copy_dartdev_snapshot",
]
}

copy("copy_dartdev_kernel") {
Expand All @@ -30,3 +33,18 @@ application_snapshot("generate_dartdev_kernel") {
inputs = dartdev_files
output = "$root_gen_dir/dartdev.dill"
}

copy("copy_dartdev_snapshot") {
visibility = [ ":dartdev" ]
public_deps = [ ":generate_dartdev_snapshot" ]
sources = [ "$root_gen_dir/dartdev.dart.snapshot" ]
outputs = [ "$root_out_dir/dartdev.dart.snapshot" ]
}

application_snapshot("generate_dartdev_snapshot") {
main_dart = "../../pkg/dartdev/bin/dartdev.dart"
training_args = [ "--help" ]
deps = [ "../dds:dds" ]
inputs = dartdev_files
output = "$root_gen_dir/dartdev.dart.snapshot"
}

0 comments on commit c42c76f

Please sign in to comment.