Changes to make isolate reload functionality work with the --dfe option.

R=aam@google.com, rmacnak@google.com

Review-Url: https://codereview.chromium.org/2894773004 .
This commit is contained in:
Siva Annamalai 2017-05-25 15:40:36 -07:00
parent a865f0ecf2
commit 286dd51948
10 changed files with 224 additions and 75 deletions

View file

@ -293,6 +293,8 @@ executable("gen_snapshot") {
# Very limited native resolver provided.
"builtin_common.cc",
"builtin_gen_snapshot.cc",
"dfe.cc",
"dfe.h",
"gen_snapshot.cc",
"vmservice_impl.cc",
"vmservice_impl.h",
@ -669,6 +671,8 @@ dart_executable("dart") {
]
extra_sources = [
"builtin_nolib.cc",
"dfe.cc",
"dfe.h",
"loader.cc",
"loader.h",
]
@ -715,6 +719,8 @@ dart_executable("dart_bootstrap") {
extra_sources = [
"builtin.cc",
"builtin.h",
"dfe.cc",
"dfe.h",
"loader.cc",
"loader.h",
"observatory_assets_empty.cc",
@ -857,6 +863,8 @@ executable("run_vm_tests") {
"snapshot_utils.h",
"builtin_nolib.cc",
"run_vm_tests.cc",
"dfe.cc",
"dfe.h",
] + builtin_impl_tests_list + vm_tests
if (!is_win) {

View file

@ -953,6 +953,8 @@
'builtin_common.cc',
'builtin.cc',
'builtin.h',
'dfe.cc',
'dfe.h',
'loader.cc',
'loader.h',
'platform_android.cc',
@ -1129,12 +1131,14 @@
'builtin_common.cc',
'builtin_natives.cc',
'builtin_nolib.cc',
'dfe.cc',
'dfe.h',
'error_exit.cc',
'error_exit.h',
'io_natives.h',
'main.cc',
'loader.cc',
'loader.h',
'main.cc',
'snapshot_utils.cc',
'snapshot_utils.h',
'vmservice_impl.cc',
@ -1246,12 +1250,14 @@
'builtin.h',
'builtin_common.cc',
'builtin_natives.cc',
'dfe.cc',
'dfe.h',
'error_exit.cc',
'error_exit.h',
'io_natives.h',
'main.cc',
'loader.cc',
'loader.h',
'main.cc',
'observatory_assets_empty.cc',
'snapshot_empty.cc',
'snapshot_utils.cc',
@ -1334,6 +1340,8 @@
'builtin_natives.cc',
'builtin_nolib.cc',
'builtin.h',
'dfe.cc',
'dfe.h',
'io_natives.h',
'loader.cc',
'loader.h',

View file

@ -60,39 +60,6 @@ MagicNumberData snapshot_magic_number = {{0xf5, 0xf5, 0xdc, 0xdc}, true};
MagicNumberData kernel_magic_number = {{0x90, 0xab, 0xcd, 0xef}, false};
bool TryReadKernel(const char* script_uri,
const uint8_t** kernel_file,
intptr_t* kernel_length) {
*kernel_file = NULL;
*kernel_length = -1;
bool is_kernel_file = false;
void* script_file = DartUtils::OpenFile(script_uri, false);
if (script_file != NULL) {
const uint8_t* buffer = NULL;
DartUtils::ReadFile(&buffer, kernel_length, script_file);
DartUtils::CloseFile(script_file);
if (*kernel_length > 0 && buffer != NULL) {
// We need a temporary variable because SniffForMagicNumber modifies the
// buffer pointer to skip snapshot magic number.
const uint8_t* temp = buffer;
if (DartUtils::SniffForMagicNumber(&temp, kernel_length) !=
DartUtils::kKernelMagicNumber) {
free(const_cast<uint8_t*>(buffer));
*kernel_file = NULL;
} else {
// Do not free buffer if this is a kernel file - kernel_file will be
// backed by the same memory as the buffer and caller will own it.
// Caller is responsible for freeing the buffer when this function
// returns true.
is_kernel_file = true;
*kernel_file = buffer;
}
}
}
return is_kernel_file;
}
static bool IsWindowsHost() {
#if defined(HOST_OS_WINDOWS)
return true;

View file

@ -33,14 +33,6 @@ static inline Dart_Handle ThrowIfError(Dart_Handle handle) {
return handle;
}
// Tries to read [script_uri] as a Kernel IR file. If successful this function
// returns `true` and sets [kernel_file] and [kernel_length] to be the memory
// contents.
//
// The caller is responsible for free()ing [kernel_file] if `true` was returned.
bool TryReadKernel(const char* script_uri,
const uint8_t** kernel_file,
intptr_t* kernel_length);
class CommandLineOptions {
public:

93
runtime/bin/dfe.cc Normal file
View file

@ -0,0 +1,93 @@
// Copyright (c) 2017, 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.
#include "bin/dfe.h"
#include "bin/dartutils.h"
namespace dart {
namespace bin {
DFE::DFE() : frontend_filename_(NULL), platform_binary_filename_(NULL) {}
DFE::~DFE() {
frontend_filename_ = NULL;
platform_binary_filename_ = NULL;
}
Dart_Handle DFE::ReloadScript(Dart_Isolate isolate, Dart_Handle url) {
ASSERT(!Dart_IsServiceIsolate(isolate) && !Dart_IsKernelIsolate(isolate));
const char* url_string = NULL;
Dart_Handle result = Dart_StringToCString(url, &url_string);
if (Dart_IsError(result)) {
return result;
}
// First check if the URL points to a Kernel IR file in which case we
// skip the compilation step and directly reload the file.
const uint8_t* kernel_ir = NULL;
intptr_t kernel_ir_size = -1;
if (!TryReadKernelFile(url_string, &kernel_ir, &kernel_ir_size)) {
// We have a source file, compile it into a kernel ir first.
// TODO(asiva): We will have to change this API to pass in a list of files
// that have changed. For now just pass in the main url_string and have it
// recompile the script.
Dart_KernelCompilationResult kresult = Dart_CompileToKernel(url_string);
if (kresult.status != Dart_KernelCompilationStatus_Ok) {
return Dart_NewApiError(kresult.error);
}
kernel_ir = kresult.kernel;
kernel_ir_size = kresult.kernel_size;
}
void* kernel_program = Dart_ReadKernelBinary(kernel_ir, kernel_ir_size);
ASSERT(kernel_program != NULL);
result = Dart_LoadKernel(kernel_program);
if (Dart_IsError(result)) {
return result;
}
// Finalize loading. This will complete any futures for completed deferred
// loads.
result = Dart_FinalizeLoading(true);
if (Dart_IsError(result)) {
return result;
}
return Dart_Null();
}
bool DFE::TryReadKernelFile(const char* script_uri,
const uint8_t** kernel_ir,
intptr_t* kernel_ir_size) {
*kernel_ir = NULL;
*kernel_ir_size = -1;
void* script_file = DartUtils::OpenFile(script_uri, false);
if (script_file != NULL) {
const uint8_t* buffer = NULL;
DartUtils::ReadFile(&buffer, kernel_ir_size, script_file);
DartUtils::CloseFile(script_file);
if (*kernel_ir_size > 0 && buffer != NULL) {
// We need a temporary variable because SniffForMagicNumber modifies the
// buffer pointer to skip snapshot magic number.
const uint8_t* temp = buffer;
if (DartUtils::SniffForMagicNumber(&temp, kernel_ir_size) !=
DartUtils::kKernelMagicNumber) {
free(const_cast<uint8_t*>(buffer));
*kernel_ir = NULL;
*kernel_ir_size = -1;
return false;
} else {
// Do not free buffer if this is a kernel file - kernel_file will be
// backed by the same memory as the buffer and caller will own it.
// Caller is responsible for freeing the buffer when this function
// returns true.
*kernel_ir = buffer;
return true;
}
}
}
return false;
}
} // namespace bin
} // namespace dart

58
runtime/bin/dfe.h Normal file
View file

@ -0,0 +1,58 @@
// Copyright (c) 2017, 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.
#ifndef RUNTIME_BIN_DFE_H_
#define RUNTIME_BIN_DFE_H_
#include "include/dart_api.h"
#include "include/dart_native_api.h"
#include "platform/assert.h"
#include "platform/globals.h"
namespace dart {
namespace bin {
class DFE {
public:
DFE();
~DFE();
const char* frontend_filename() const { return frontend_filename_; }
void set_frontend_filename(const char* name) { frontend_filename_ = name; }
bool UseDartFrontend() const { return frontend_filename_ != NULL; }
const char* platform_binary_filename() const {
return platform_binary_filename_;
}
void set_platform_binary_filename(const char* name) {
platform_binary_filename_ = name;
}
bool UsePlatformBinary() const { return platform_binary_filename_ != NULL; }
// Method to reload a script into a running a isolate.
// If the specified script [url] is not a kernel IR, compile it first using
// DFE and then reload the resulting kernel IR into the isolate.
// Returns Dart_Null if successful, otherwise an error object is returned.
Dart_Handle ReloadScript(Dart_Isolate isolate, Dart_Handle url);
// Tries to read [script_uri] as a Kernel IR file.
// Returns `true` if successful and sets [kernel_file] and [kernel_length]
// to be the kernel IR contents.
// The caller is responsible for free()ing [kernel_file] if `true`
// was returned.
bool TryReadKernelFile(const char* script_uri,
const uint8_t** kernel_ir,
intptr_t* kernel_ir_size);
private:
const char* frontend_filename_;
const char* platform_binary_filename_;
DISALLOW_COPY_AND_ASSIGN(DFE);
};
} // namespace bin
} // namespace dart
#endif // RUNTIME_BIN_DFE_H_

View file

@ -13,6 +13,7 @@
#include "bin/builtin.h"
#include "bin/dartutils.h"
#include "bin/dfe.h"
#include "bin/eventhandler.h"
#include "bin/file.h"
#include "bin/loader.h"
@ -31,6 +32,8 @@
namespace dart {
namespace bin {
DFE dfe;
// Exit code indicating an API error.
static const int kApiErrorExitCode = 253;
// Exit code indicating a compilation error.
@ -1570,7 +1573,7 @@ int main(int argc, char** argv) {
const uint8_t* kernel = NULL;
intptr_t kernel_length = 0;
const bool is_kernel_file =
TryReadKernel(app_script_name, &kernel, &kernel_length);
dfe.TryReadKernelFile(app_script_name, &kernel, &kernel_length);
if ((dependencies_filename != NULL) || print_dependencies) {
isolate_data->set_dependencies(new MallocGrowableArray<char*>());

View file

@ -7,6 +7,7 @@
#include "bin/builtin.h"
#include "bin/dartutils.h"
#include "bin/dfe.h"
#include "bin/extensions.h"
#include "bin/file.h"
#include "bin/lockers.h"
@ -19,6 +20,10 @@ namespace bin {
// Development flag.
static bool trace_loader = false;
#if !defined(DART_PRECOMPILED_RUNTIME)
extern DFE dfe;
#endif
// Keep in sync with loader.dart.
static const intptr_t _Dart_kImportExtension = 9;
static const intptr_t _Dart_kResolveAsFilePath = 10;
@ -638,6 +643,19 @@ Dart_Handle Loader::DartColonLibraryTagHandler(Dart_LibraryTag tag,
Dart_Handle Loader::LibraryTagHandler(Dart_LibraryTag tag,
Dart_Handle library,
Dart_Handle url) {
if (dfe.UseDartFrontend()) {
Dart_Isolate current = Dart_CurrentIsolate();
if (!Dart_IsServiceIsolate(current) && !Dart_IsKernelIsolate(current)) {
// When using DFE the library tag handler should be called only when we
// are reloading scripts.
// TODO(asiva) We need to ensure that the kernel and service isolates
// and the spawnURI paths are always loaded from a kernel IR and do
// not use this path.
if (tag == Dart_kScriptTag) {
return dfe.ReloadScript(current, url);
}
}
}
if (tag == Dart_kCanonicalizeUrl) {
Dart_Handle library_url = Dart_LibraryUrl(library);
if (Dart_IsError(library_url)) {

View file

@ -11,6 +11,7 @@
#include "bin/builtin.h"
#include "bin/dartutils.h"
#include "bin/dfe.h"
#include "bin/directory.h"
#include "bin/embedded_dart_io.h"
#include "bin/error_exit.h"
@ -78,15 +79,9 @@ enum SnapshotKind {
};
static SnapshotKind gen_snapshot_kind = kNone;
static const char* snapshot_deps_filename = NULL;
static bool use_dart_frontend = false;
static const char* frontend_filename = NULL;
// True if the VM should boostrap the SDK from a binary (.dill) file. The
// filename points into an argv buffer and does not need to be freed.
static bool use_platform_binary = false;
static const char* platform_binary_filename = NULL;
#if !defined(DART_PRECOMPILED_RUNTIME)
DFE dfe;
#endif
// Value of the --save-feedback flag.
// (This pointer points into an argv buffer and does not need to be
@ -340,14 +335,14 @@ static bool ProcessParseAllOption(const char* arg,
}
#if !defined(DART_PRECOMPILED_RUNTIME)
static bool ProcessFrontendOption(const char* filename,
CommandLineOptions* vm_options) {
ASSERT(filename != NULL);
if (filename[0] == '\0') {
return false;
}
use_dart_frontend = true;
frontend_filename = filename;
dfe.set_frontend_filename(filename);
vm_options->AddArgument("--use-dart-frontend");
return true;
}
@ -359,10 +354,10 @@ static bool ProcessPlatformOption(const char* filename,
if (filename[0] == '\0') {
return false;
}
use_platform_binary = true;
platform_binary_filename = filename;
dfe.set_platform_binary_filename(filename);
return true;
}
#endif
static bool ProcessUseBlobsOption(const char* arg,
@ -588,8 +583,10 @@ static struct {
// VM specific options to the standalone dart program.
{"--compile_all", ProcessCompileAllOption},
{"--parse_all", ProcessParseAllOption},
#if !defined(DART_PRECOMPILED_RUNTIME)
{"--dfe=", ProcessFrontendOption},
{"--platform=", ProcessPlatformOption},
#endif
{"--enable-vm-service", ProcessEnableVmServiceOption},
{"--disable-service-origin-check", ProcessDisableServiceOriginCheckOption},
{"--observe", ProcessObserveOption},
@ -837,19 +834,6 @@ static Dart_Isolate CreateIsolateAndSetupHelper(bool is_main_isolate,
char** error,
int* exit_code) {
ASSERT(script_uri != NULL);
const bool is_kernel_isolate =
strcmp(script_uri, DART_KERNEL_ISOLATE_NAME) == 0;
if (is_kernel_isolate) {
if (!use_dart_frontend) {
*error = strdup("Kernel isolate not supported.");
return NULL;
}
script_uri = frontend_filename;
if (packages_config == NULL) {
packages_config = commandline_packages_file;
}
}
void* kernel_platform = NULL;
void* kernel_program = NULL;
AppSnapshot* app_snapshot = NULL;
@ -867,6 +851,18 @@ static Dart_Isolate CreateIsolateAndSetupHelper(bool is_main_isolate,
const uint8_t* isolate_snapshot_data = core_isolate_snapshot_data;
const uint8_t* isolate_snapshot_instructions =
core_isolate_snapshot_instructions;
const bool is_kernel_isolate =
strcmp(script_uri, DART_KERNEL_ISOLATE_NAME) == 0;
if (is_kernel_isolate) {
if (!dfe.UseDartFrontend()) {
*error = strdup("Kernel isolate not supported.");
return NULL;
}
script_uri = dfe.frontend_filename();
if (packages_config == NULL) {
packages_config = commandline_packages_file;
}
}
if ((app_isolate_snapshot_data != NULL) &&
(is_main_isolate || ((app_script_uri != NULL) &&
(strcmp(script_uri, app_script_uri) == 0)))) {
@ -888,10 +884,10 @@ static Dart_Isolate CreateIsolateAndSetupHelper(bool is_main_isolate,
strcmp(script_uri, DART_VM_SERVICE_ISOLATE_NAME) == 0;
if (!is_kernel_isolate && !is_service_isolate) {
const uint8_t* platform_file = NULL;
if (use_platform_binary) {
if (dfe.UsePlatformBinary()) {
intptr_t platform_length = -1;
bool success = TryReadKernel(platform_binary_filename, &platform_file,
&platform_length);
bool success = dfe.TryReadKernelFile(dfe.platform_binary_filename(),
&platform_file, &platform_length);
if (!success) {
*error = strdup("The platform binary is not a valid Dart Kernel file.");
*exit_code = kErrorExitCode;
@ -903,7 +899,7 @@ static Dart_Isolate CreateIsolateAndSetupHelper(bool is_main_isolate,
bool is_kernel = false;
const uint8_t* kernel_file = NULL;
intptr_t kernel_length = -1;
if (use_dart_frontend) {
if (dfe.UseDartFrontend()) {
Dart_KernelCompilationResult result = Dart_CompileToKernel(script_uri);
*error = result.error; // Copy error message (if any).
switch (result.status) {
@ -928,7 +924,8 @@ static Dart_Isolate CreateIsolateAndSetupHelper(bool is_main_isolate,
return NULL;
}
} else if (!isolate_run_app_snapshot) {
is_kernel = TryReadKernel(script_uri, &kernel_file, &kernel_length);
is_kernel =
dfe.TryReadKernelFile(script_uri, &kernel_file, &kernel_length);
}
if (is_kernel) {

View file

@ -5,6 +5,7 @@
#include <stdio.h>
#include "bin/dartutils.h"
#include "bin/dfe.h"
#include "bin/file.h"
#include "bin/loader.h"
#include "bin/platform.h"
@ -24,6 +25,10 @@ extern const uint8_t kDartCoreIsolateSnapshotInstructions[];
// TODO(iposva, asiva): This is a placeholder for the real unittest framework.
namespace dart {
namespace bin {
DFE dfe;
}
// Defined in vm/os_thread_win.cc
extern bool private_flag_windows_run_tls_destructors;