Files
sdk/runtime/bin/vmservice_impl.cc
T
asiva 5399dbf6f6 [VM/dartdev] Switch dartdev to use an AOT runtime.
- split the Dart CLI tool out of the VM into it's own embedder which
  runs in AOT mode. The pure Dart VM executable is called 'dartvm' and
  has no Dart CLI functionality in it
- the Dart CLI executable parses the CLI commands and invokes the rest
  of the AOT tools in the same process, for the 'run' and 'test'
  commands it execs a process which runs 'dartvm' to run
- 'dart hello.dart' execs the 'dartvm' process and runs 'hello.dart'
- the Dart CLI is not generated for ia32 as we are not shipping a
  Dart SDK for ia32 anymore (support to execute the 'dartvm' for ia32
  architecture is retained)
- the Dart CLI tool is not built in the internal Dart SDK builds

TEST=ci

Some performance improvement numbers
'dart format pkg/dartdev' goes from 1.17 secs to 0.22 secs
'dart doc pkg/dartdev' goes from 100.2 secs to 66.6 secs
'dart fix pkg/dartdev' goes from 19.3 secs to 14.5 secs

Change-Id: I66984a26cb2ab014b34dc1873f1f3d2884e13518
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/364202
Commit-Queue: Ben Konyi <bkonyi@google.com>
Reviewed-by: Ben Konyi <bkonyi@google.com>
2025-07-04 13:22:13 -07:00

299 lines
10 KiB
C++

// Copyright (c) 2013, 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/vmservice_impl.h"
#include "include/dart_api.h"
#include "bin/builtin.h"
#include "bin/dartutils.h"
#include "bin/isolate_data.h"
#include "bin/platform.h"
#include "bin/thread.h"
#include "bin/utils.h"
#include "platform/text_buffer.h"
#include "platform/utils.h"
namespace dart {
namespace bin {
#if !defined(PRODUCT)
#define RETURN_ERROR_HANDLE(handle) \
if (Dart_IsError(handle)) { \
return handle; \
}
#define SHUTDOWN_ON_ERROR(handle) \
if (Dart_IsError(handle)) { \
error_msg_ = Utils::StrDup(Dart_GetError(handle)); \
Dart_ExitScope(); \
Dart_ShutdownIsolate(); \
return false; \
}
static constexpr const char* kVMServiceIOLibraryUri = "dart:vmservice_io";
static constexpr const char* DEFAULT_VM_SERVICE_SERVER_IP = "localhost";
void NotifyServerState(Dart_NativeArguments args) {
Dart_EnterScope();
const char* uri_chars;
Dart_Handle uri_arg = Dart_GetNativeArgument(args, 0);
if (Dart_IsError(uri_arg)) {
VmService::SetServerAddress("");
Dart_ExitScope();
return;
}
Dart_Handle result = Dart_StringToCString(uri_arg, &uri_chars);
if (Dart_IsError(result)) {
VmService::SetServerAddress("");
Dart_ExitScope();
return;
}
VmService::SetServerAddress(uri_chars);
Dart_ExitScope();
}
static void Shutdown(Dart_NativeArguments args) {
// NO-OP.
}
struct VmServiceIONativeEntry {
const char* name;
int num_arguments;
Dart_NativeFunction function;
};
static VmServiceIONativeEntry _VmServiceIONativeEntries[] = {
{"VMServiceIO_NotifyServerState", 1, NotifyServerState},
{"VMServiceIO_Shutdown", 0, Shutdown},
};
static Dart_NativeFunction VmServiceIONativeResolver(Dart_Handle name,
int num_arguments,
bool* auto_setup_scope) {
const char* function_name = nullptr;
Dart_Handle result = Dart_StringToCString(name, &function_name);
ASSERT(!Dart_IsError(result));
ASSERT(function_name != nullptr);
*auto_setup_scope = true;
intptr_t n =
sizeof(_VmServiceIONativeEntries) / sizeof(_VmServiceIONativeEntries[0]);
for (intptr_t i = 0; i < n; i++) {
VmServiceIONativeEntry entry = _VmServiceIONativeEntries[i];
if ((strcmp(function_name, entry.name) == 0) &&
(num_arguments == entry.num_arguments)) {
return entry.function;
}
}
return nullptr;
}
const uint8_t* VmServiceIONativeSymbol(Dart_NativeFunction nf) {
intptr_t n =
sizeof(_VmServiceIONativeEntries) / sizeof(_VmServiceIONativeEntries[0]);
for (intptr_t i = 0; i < n; i++) {
VmServiceIONativeEntry entry = _VmServiceIONativeEntries[i];
if (reinterpret_cast<Dart_NativeFunction>(entry.function) == nf) {
return reinterpret_cast<const uint8_t*>(entry.name);
}
}
return nullptr;
}
const char* VmService::error_msg_ = nullptr;
char VmService::server_uri_[kServerUriStringBufferSize];
void VmService::SetNativeResolver() {
Dart_Handle url = DartUtils::NewString(kVMServiceIOLibraryUri);
Dart_Handle library = Dart_LookupLibrary(url);
if (!Dart_IsError(library)) {
Dart_SetNativeResolver(library, VmServiceIONativeResolver,
VmServiceIONativeSymbol);
}
}
bool VmService::Setup(const char* server_ip,
intptr_t server_port,
bool dev_mode_server,
bool auth_codes_disabled,
const char* write_service_info_filename,
bool trace_loading,
bool deterministic,
bool enable_service_port_fallback,
bool wait_for_dds_to_advertise_service,
bool serve_devtools,
bool serve_observatory,
bool print_dtd,
bool should_use_resident_compiler,
const char* resident_compiler_info_file_path) {
Dart_Isolate isolate = Dart_CurrentIsolate();
ASSERT(isolate != nullptr);
SetServerAddress("");
Dart_Handle result;
// Prepare builtin and its dependent libraries for use to resolve URIs.
// Set up various closures, e.g: printing, timers etc.
// Set up 'package root' for URI resolution.
result = DartUtils::PrepareForScriptLoading(
/*is_service_isolate=*/true, trace_loading,
/*flag_profile_microtasks=*/false);
SHUTDOWN_ON_ERROR(result);
Dart_Handle url = DartUtils::NewString(kVMServiceIOLibraryUri);
Dart_Handle library = Dart_LookupLibrary(url);
SHUTDOWN_ON_ERROR(library);
result = Dart_SetRootLibrary(library);
SHUTDOWN_ON_ERROR(library);
result = Dart_SetNativeResolver(library, VmServiceIONativeResolver,
VmServiceIONativeSymbol);
SHUTDOWN_ON_ERROR(result);
// Make runnable.
Dart_ExitScope();
Dart_ExitIsolate();
error_msg_ = Dart_IsolateMakeRunnable(isolate);
if (error_msg_ != nullptr) {
Dart_EnterIsolate(isolate);
Dart_ShutdownIsolate();
return false;
}
Dart_EnterIsolate(isolate);
Dart_EnterScope();
library = Dart_RootLibrary();
SHUTDOWN_ON_ERROR(library);
// Set HTTP server state.
// If we have a port specified, start the server immediately.
bool auto_start = server_port >= 0;
if (server_port < 0) {
// Adjust server_port to port 0 which will result in the first available
// port when the HTTP server is started.
server_port = 0;
}
if (wait_for_dds_to_advertise_service) {
result = DartUtils::SetStringField(library, "_ddsIP", server_ip);
SHUTDOWN_ON_ERROR(result);
result = DartUtils::SetIntegerField(library, "_ddsPort", server_port);
SHUTDOWN_ON_ERROR(result);
result =
DartUtils::SetStringField(library, "_ip", DEFAULT_VM_SERVICE_SERVER_IP);
SHUTDOWN_ON_ERROR(result);
result = DartUtils::SetIntegerField(library, "_port", 0);
SHUTDOWN_ON_ERROR(result);
} else {
result = DartUtils::SetStringField(library, "_ip", server_ip);
SHUTDOWN_ON_ERROR(result);
result = DartUtils::SetIntegerField(library, "_port", server_port);
SHUTDOWN_ON_ERROR(result);
}
result = Dart_SetField(library, DartUtils::NewString("_autoStart"),
Dart_NewBoolean(auto_start));
SHUTDOWN_ON_ERROR(result);
result = Dart_SetField(library, DartUtils::NewString("_originCheckDisabled"),
Dart_NewBoolean(dev_mode_server));
SHUTDOWN_ON_ERROR(result);
result = Dart_SetField(library, DartUtils::NewString("_authCodesDisabled"),
Dart_NewBoolean(auth_codes_disabled));
SHUTDOWN_ON_ERROR(result);
result =
Dart_SetField(library, DartUtils::NewString("_enableServicePortFallback"),
Dart_NewBoolean(enable_service_port_fallback));
SHUTDOWN_ON_ERROR(result);
if (write_service_info_filename != nullptr) {
result = DartUtils::SetStringField(library, "_serviceInfoFilename",
write_service_info_filename);
SHUTDOWN_ON_ERROR(result);
}
result = Dart_SetField(library,
DartUtils::NewString("_waitForDdsToAdvertiseService"),
Dart_NewBoolean(wait_for_dds_to_advertise_service));
SHUTDOWN_ON_ERROR(result);
result = Dart_SetField(library, DartUtils::NewString("_serveDevtools"),
serve_devtools ? Dart_True() : Dart_False());
SHUTDOWN_ON_ERROR(result);
result = Dart_SetField(library, DartUtils::NewString("_printDtd"),
print_dtd ? Dart_True() : Dart_False());
SHUTDOWN_ON_ERROR(result);
if (should_use_resident_compiler) {
Dart_Handle resident_compiler_info_file_path_dart_string = nullptr;
if (resident_compiler_info_file_path == nullptr) {
resident_compiler_info_file_path_dart_string = Dart_Null();
} else {
resident_compiler_info_file_path_dart_string =
DartUtils::NewString(resident_compiler_info_file_path);
}
result = Dart_Invoke(
library, DartUtils::NewString("_populateResidentCompilerInfoFile"), 1,
&resident_compiler_info_file_path_dart_string);
SHUTDOWN_ON_ERROR(result);
}
// Are we running on Windows?
#if defined(DART_HOST_OS_WINDOWS)
Dart_Handle is_windows = Dart_True();
#else
Dart_Handle is_windows = Dart_False();
#endif
result =
Dart_SetField(library, DartUtils::NewString("_isWindows"), is_windows);
SHUTDOWN_ON_ERROR(result);
// Are we running on Fuchsia?
#if defined(DART_HOST_OS_FUCHSIA)
Dart_Handle is_fuchsia = Dart_True();
#else
Dart_Handle is_fuchsia = Dart_False();
#endif
result =
Dart_SetField(library, DartUtils::NewString("_isFuchsia"), is_fuchsia);
SHUTDOWN_ON_ERROR(result);
// Get _getWatchSignalInternal from dart:io.
Dart_Handle dart_io_str = Dart_NewStringFromCString(DartUtils::kIOLibURL);
SHUTDOWN_ON_ERROR(dart_io_str);
Dart_Handle io_lib = Dart_LookupLibrary(dart_io_str);
SHUTDOWN_ON_ERROR(io_lib);
Dart_Handle function_name =
Dart_NewStringFromCString("_getWatchSignalInternal");
SHUTDOWN_ON_ERROR(function_name);
Dart_Handle signal_watch = Dart_Invoke(io_lib, function_name, 0, nullptr);
SHUTDOWN_ON_ERROR(signal_watch);
Dart_Handle field_name = Dart_NewStringFromCString("_signalWatch");
SHUTDOWN_ON_ERROR(field_name);
result = Dart_SetField(library, field_name, signal_watch);
SHUTDOWN_ON_ERROR(field_name);
return true;
}
const char* VmService::GetErrorMessage() {
return (error_msg_ == nullptr) ? "No error." : error_msg_;
}
void VmService::SetServerAddress(const char* server_uri) {
if (server_uri == nullptr) {
server_uri = "";
}
const intptr_t server_uri_len = strlen(server_uri);
if (server_uri_len >= (kServerUriStringBufferSize - 1)) {
FATAL("vm-service: Server URI exceeded length: %s\n", server_uri);
}
strncpy(server_uri_, server_uri, kServerUriStringBufferSize);
server_uri_[kServerUriStringBufferSize - 1] = '\0';
}
#endif // !defined(PRODUCT)
} // namespace bin
} // namespace dart