diff --git a/pkg/dartdev/test/load_from_dill_test.dart b/pkg/dartdev/test/load_from_dill_test.dart new file mode 100644 index 00000000000..6de6c6c5d1b --- /dev/null +++ b/pkg/dartdev/test/load_from_dill_test.dart @@ -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); + }); +} diff --git a/runtime/bin/dartdev_isolate.cc b/runtime/bin/dartdev_isolate.cc index df01614e38c..468ef64ee8d 100644 --- a/runtime/bin/dartdev_isolate.cc +++ b/runtime/bin/dartdev_isolate.cc @@ -57,13 +57,14 @@ 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); } @@ -71,7 +72,7 @@ Utils::CStringUniquePtr DartDevIsolate::TryResolveDartDevSnapshotPath() { // 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); } @@ -79,6 +80,14 @@ Utils::CStringUniquePtr DartDevIsolate::TryResolveDartDevSnapshotPath() { 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, diff --git a/runtime/bin/dartdev_isolate.h b/runtime/bin/dartdev_isolate.h index 8fd0bd9bc26..a25664c3a07 100644 --- a/runtime/bin/dartdev_isolate.h +++ b/runtime/bin/dartdev_isolate.h @@ -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. @@ -89,6 +91,8 @@ class DartDevIsolate { }; private: + static Utils::CStringUniquePtr TryResolveArtifactPath(const char* filename); + static DartDevRunner runner_; static bool should_run_dart_dev_; diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc index 7299ade79ce..cdffae9fc78 100644 --- a/runtime/bin/main.cc +++ b/runtime/bin/main.cc @@ -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, diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn index efa745ab62a..42143117ec4 100644 --- a/sdk/BUILD.gn +++ b/sdk/BUILD.gn @@ -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 @@ -117,6 +118,10 @@ _platform_sdk_snapshots = [ "dartanalyzer", "../utils/dartanalyzer:generate_dartanalyzer_snapshot", ], + [ + "dartdev", + "../utils/dartdev:dartdev", + ], [ "dartdoc", "../utils/dartdoc", @@ -162,6 +167,10 @@ _full_sdk_snapshots = [ "dartanalyzer", "../utils/dartanalyzer:generate_dartanalyzer_snapshot", ], + [ + "dartdev", + "../utils/dartdev:generate_dartdev_snapshot", + ], [ "dartdevc", "../utils/dartdevc", diff --git a/utils/dartdev/BUILD.gn b/utils/dartdev/BUILD.gn index 02823aefcc4..c7d8c12b1d6 100644 --- a/utils/dartdev/BUILD.gn +++ b/utils/dartdev/BUILD.gn @@ -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") { @@ -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" +}