[Service] Add support for resident frontend server to package:dart_runtime_service_vm

TEST=Existing, ran locally.
Change-Id: Idc1f35eb3d4cf0c7251a64b02b801e8110cc323b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/499000
Reviewed-by: Nicholas Shahan <nshahan@google.com>
Commit-Queue: Ben Konyi <bkonyi@google.com>
This commit is contained in:
Ben Konyi
2026-04-30 17:04:19 -07:00
committed by dart-scoped@luci-project-accounts.iam.gserviceaccount.com
parent 521b102563
commit 0b68c62fc5
13 changed files with 375 additions and 71 deletions
@@ -5,6 +5,7 @@
import 'dart:async';
import 'dart:io';
import 'dart:isolate';
import 'dart:vmservice_io' show getResidentCompilerInfoFileConsideringArgsImpl;
import 'package:dart_runtime_service/dart_runtime_service.dart';
import 'package:dart_runtime_service_vm/dart_runtime_service_vm.dart';
@@ -90,19 +91,23 @@ bool _waitForDdsToAdvertiseService = false;
@entrypoint
bool _printDtd = false;
// ignore: unused_element
File? _residentCompilerInfoFile;
@entrypoint
/// Sets the resident compiler info file, which is used to configure the
/// service to utilize a resident compiler.
///
/// If either `--resident-compiler-info-file` or `--resident-server-info-file`
/// was supplied on the command line, the CLI argument should be forwarded as
/// the argument to [residentCompilerInfoFilePathArgumentFromCli]. If neither
/// option was supplied, the argument to this parameter should be null.
// ignore: unused_element
void _populateResidentCompilerInfoFile(
/// If either `--resident-compiler-info-file` or `--resident-server-info-file`
/// was supplied on the command line, the CLI argument should be forwarded as
/// the argument to this parameter. If neither option was supplied, the
/// argument to this parameter should be null.
String? residentCompilerInfoFilePathArgumentFromCli,
) {
// TODO(bkonyi): implement
_residentCompilerInfoFile = getResidentCompilerInfoFileConsideringArgsImpl(
residentCompilerInfoFilePathArgumentFromCli,
);
}
@pragma('vm:entry-point', 'get')
@@ -131,6 +136,7 @@ Future<void> main([List<String> args = const []]) async {
host: _ddsIP,
port: _ddsPort,
),
residentCompilerInfoFile: _residentCompilerInfoFile,
),
);
}
@@ -33,6 +33,7 @@ class DartRuntimeServiceVMBackend
required super.frontend,
required this.signalWatch,
required Stream<VmRunningIsolate> runningIsolatesStream,
required this.residentCompilerInfoFile,
required this._ddsManager,
}) : isolateManager = VmIsolateManager(
runningIsolatesStream: runningIsolatesStream,
@@ -82,6 +83,8 @@ class DartRuntimeServiceVMBackend
late final _vmServiceRpcs = DartRuntimeServiceVmRpcs(backend: this);
final File? residentCompilerInfoFile;
/// Adds support for launching and accepting connections from the
/// Dart Development Service.
final DartDevelopmentServiceManager _ddsManager;
@@ -5,6 +5,9 @@
import 'dart:collection';
import 'package:dart_runtime_service/dart_runtime_service.dart';
import 'package:file/local.dart';
import 'package:frontend_server/resident_frontend_server_utils.dart'
as frontend_server;
import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc_2;
import 'package:logging/logging.dart';
import 'package:vm_service/vm_service.dart';
@@ -26,16 +29,22 @@ final class DartRuntimeServiceVmRpcs {
static const _kCreateIdZone = 'createIdZone';
static const _kDeleteIdZone = 'deleteIdZone';
static const _kStreamCpuSamplesWithUserTag = 'streamCpuSamplesWithUserTag';
static const _kReloadSources = 'reloadSources';
static const _kReloadKernel = '_reloadKernel';
static const _kIsolateId = 'isolateId';
static const _kIdZoneId = 'idZoneId';
static const _kUserTags = 'userTags';
static const _kRootLibUri = 'rootLibUri';
static const _kForce = 'force';
static const _kKernelFilePath = 'kernelFilePath';
late final rpcs = UnmodifiableListView<ServiceRpcHandler>([
(_kGetSupportedProtocols, getSupportedProtocols),
(_kCreateIdZone, createIdZone),
(_kDeleteIdZone, deleteIdZone),
(_kStreamCpuSamplesWithUserTag, streamCpuSamplesWithUserTag),
(_kReloadSources, reloadSources),
]);
/// Returns the list of protocols implemented by the service.
@@ -108,4 +117,64 @@ final class DartRuntimeServiceVmRpcs {
parameters[_kUserTags].asList;
return Success().toJson();
}
/// Performs a hot reload of the sources of all isolates in the same isolate
/// group as the isolate specified by `isolateId`.
Future<RpcResponse> reloadSources(json_rpc_2.Parameters parameters) async {
final isolateId = parameters[_kIsolateId].asString;
final residentCompilerInfoFile = backend.residentCompilerInfoFile;
if (residentCompilerInfoFile == null ||
!residentCompilerInfoFile.existsSync()) {
_logger.info(
'Resident compiler not configured: $residentCompilerInfoFile.',
);
return backend.sendToRuntime(parameters);
}
_logger.info(
'Resident compiler is configured and will be used to compile '
'sources to kernel before reloading.',
);
var rootLibUri = parameters[_kRootLibUri].exists
? parameters[_kRootLibUri].asString
: null;
if (rootLibUri == null) {
final result = Isolate.parse(
await backend.isolateManager.sendToIsolate(
method: 'getIsolate',
params: {_kIsolateId: isolateId},
),
);
rootLibUri = result!.rootLib!.uri!;
}
final tempDir = const LocalFileSystem().systemTempDirectory
.createTempSync();
try {
final outputDill = tempDir.childFile('for_hot_reload.dill');
try {
await frontend_server.invokeCompile(
executable: Uri.parse(rootLibUri).toFilePath(),
outputDill: outputDill.path,
serverInfoFile: residentCompilerInfoFile,
);
} on frontend_server.CompileException catch (e) {
_logger.warning('Kernel compilation request failed: $e');
RpcException.internalError.throwExceptionWithDetails(
details: e.message,
);
}
return await backend.isolateManager.sendToIsolate(
method: _kReloadKernel,
params: {
_kIsolateId: isolateId,
_kKernelFilePath: outputDill.uri.toFilePath(),
_kForce: parameters[_kForce].asBoolOr(false),
},
);
} finally {
tempDir.deleteSync(recursive: true);
}
}
}
@@ -5,6 +5,8 @@
import 'dart:async';
import 'package:dart_runtime_service/dart_runtime_service.dart';
import 'package:frontend_server/resident_frontend_server_utils.dart'
as frontend_server;
import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
import '../dart_runtime_service_vm.dart';
@@ -162,8 +164,7 @@ final class VmExpressionEvaluator extends ExpressionEvaluator {
String expression,
ExpressionEvaluationScope scope,
) async {
final compileParams = <String, Object?>{
kIsolateId: isolateId,
final commonParams = <String, Object?>{
kExpression: expression,
kDefinitions: scope[kParamNames],
kDefinitionTypes: scope[kParamTypes],
@@ -171,12 +172,16 @@ final class VmExpressionEvaluator extends ExpressionEvaluator {
kTypeBounds: scope[kTypeParamsBounds],
kTypeDefaults: scope[kTypeParamsDefaults],
kLibraryUri: scope[kLibraryUri],
kTokenPos: scope[kTokenPos],
kIsStatic: scope[kIsStatic],
kKlass: ?scope[kKlass],
kMethod: ?scope[kMethod],
kScriptUri: ?scope[kScriptUri],
};
final compileParams = <String, Object?>{
kIsolateId: isolateId,
kTokenPos: scope[kTokenPos],
kKlass: ?scope[kKlass],
...commonParams,
};
final externalClient = clients.findFirstClientThatHandlesService(
kExternalCompileExpressionRpc,
@@ -192,6 +197,12 @@ final class VmExpressionEvaluator extends ExpressionEvaluator {
method: kExternalCompileExpressionRpc,
parameters: compileParams,
);
} else if (backend.residentCompilerInfoFile?.existsSync() ?? false) {
logger.info('Using resident frontend server for compilation.');
result = await _compileExpressionWithResidentFrontendServer(
commonParams: commonParams,
scope: scope,
);
} else {
result = await backend.sendToRuntime(
json_rpc.Parameters(kInternalCompileExpressionRpc, compileParams),
@@ -207,6 +218,48 @@ final class VmExpressionEvaluator extends ExpressionEvaluator {
}
}
Future<RpcResponse> _compileExpressionWithResidentFrontendServer({
required Map<String, Object?> commonParams,
required Map<String, Object?> scope,
}) async {
final {
kExpression: expression as String,
kDefinitions: definitions as List<Object?>,
kDefinitionTypes: definitionTypes as List<Object?>,
kTypeDefinitions: typeDefinitions as List<Object?>,
kTypeBounds: typeBounds as List<Object?>,
kTypeDefaults: typeDefaults as List<Object?>,
kLibraryUri: libraryUri as String,
kIsStatic: isStatic as bool,
} = commonParams;
final method = commonParams[kMethod] as String?;
final scriptUri = commonParams[kScriptUri] as String?;
try {
final result = await frontend_server.invokeCompileExpression(
expression: expression,
definitions: definitions.cast<String>(),
definitionTypes: definitionTypes.cast<String>(),
typeDefinitions: typeDefinitions.cast<String>(),
typeBounds: typeBounds.cast<String>(),
typeDefaults: typeDefaults.cast<String>(),
libraryUri: libraryUri,
klass: scope[kKlass] as String?,
method: method,
offset: scope[kTokenPos] as int,
scriptUri: scriptUri,
isStatic: isStatic,
serverInfoFile: backend.residentCompilerInfoFile!,
);
return {kKernelBytes: result.kernelBytes};
} on frontend_server.CompileException catch (e) {
RpcException.expressionCompilationError.throwExceptionWithDetails(
details: e.message,
);
}
}
Future<RpcResponse> _evaluateCompiledExpression({
required String isolateId,
required String expression,
@@ -73,7 +73,7 @@ final class VmIsolateManager extends IsolateManager {
/// Reports that an isolate is shutting down based on a message over the
/// service's control port.
void onIsolateShutdownMessage({required int id}) {
_logger.info('Isolate startup message received for isolate ID $id');
_logger.info('Received isolate shutdown message for isolate $id');
isolateExited(id: id);
}
+1
View File
@@ -11,6 +11,7 @@ resolution: workspace
dependencies:
dart_runtime_service: any
file: any
frontend_server: any
json_rpc_2: any
logging: any
meta: any
+6 -4
View File
@@ -325,10 +325,12 @@ class _ServiceTesteeLauncher {
}
}
void setupAddresses(Uri /*!*/ serverAddress) {
serviceWebsocketAddress =
'ws://${serverAddress.authority}${serverAddress.path}ws';
serviceHttpAddress = 'http://${serverAddress.authority}${serverAddress.path}';
void setupAddresses(Uri serverAddress) {
serviceWebsocketAddress = serverAddress.replace(
scheme: 'ws',
pathSegments: [...serverAddress.pathSegments, 'ws'],
).toString();
serviceHttpAddress = serverAddress.replace(scheme: 'http').toString();
}
class _ServiceTesterRunner {
@@ -3,7 +3,8 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:convert' show jsonDecode, jsonEncode;
import 'dart:io' show Directory, File, InternetAddress, Socket;
import 'dart:io'
show Directory, File, FileSystemException, InternetAddress, Socket;
import 'package:path/path.dart' as path;
@@ -93,12 +94,12 @@ CachedDillAndCompilerOptionsPaths computeCachedDillAndCompilerOptionsPaths(
/// with [serverInfoFile], and returns the compiler's JSON response.
///
/// Throws a [FileSystemException] if [serverInfoFile] cannot be accessed.
Future<Map<String, dynamic>> sendAndReceiveResponse(
Future<Map<String, Object?>> sendAndReceiveResponse(
String request,
File serverInfoFile,
) async {
Socket? client;
Map<String, dynamic> jsonResponse;
Map<String, Object?> jsonResponse;
final ResidentCompilerInfo residentCompilerInfo =
ResidentCompilerInfo.fromFile(serverInfoFile);
@@ -109,9 +110,9 @@ Future<Map<String, dynamic>> sendAndReceiveResponse(
);
client.write(request);
final String data = new String.fromCharCodes(await client.first);
jsonResponse = jsonDecode(data);
jsonResponse = (jsonDecode(data) as Map<String, Object?>);
} catch (e) {
jsonResponse = <String, dynamic>{
jsonResponse = <String, Object?>{
'success': false,
'errorMessage': e.toString(),
};
@@ -129,12 +130,159 @@ Future<bool> invokeReplaceCachedDill({
required String replacementDillPath,
required File serverInfoFile,
}) async {
final Map<String, dynamic> response = await sendAndReceiveResponse(
final Map<String, Object?> response = await sendAndReceiveResponse(
jsonEncode({
'command': 'replaceCachedDill',
'replacementDillPath': replacementDillPath,
}),
serverInfoFile,
);
return response['success'];
return response['success'] == true;
}
/// The result of a successful compilation request sent to a resident
/// frontend compiler.
final class CompileResult {
/// The absolute path to the kernel file produced by the compiler.
final String outputDill;
/// The number of errors produced by the compiler.
final int errorCount;
/// The output lines produced by the compiler, if any.
final List<String> compilerOutputLines;
CompileResult({
required this.outputDill,
required this.errorCount,
this.compilerOutputLines = const [],
});
}
/// The result of a successful expression compilation request sent to a
/// resident frontend compiler.
final class CompileExpressionResult {
/// The base64 encoded kernel bytes produced by the compiler.
final String kernelBytes;
/// The number of errors produced by the compiler.
final int errorCount;
/// The output lines produced by the compiler, if any.
final List<String> compilerOutputLines;
CompileExpressionResult({
required this.kernelBytes,
required this.errorCount,
this.compilerOutputLines = const [],
});
}
/// The exception thrown when a compilation request to the resident frontend
/// compiler fails.
final class CompileException implements Exception {
/// The error message from the compiler.
final String message;
CompileException(this.message);
@override
String toString() => 'CompileException: $message';
}
/// Sends a 'compile' request to the resident frontend compiler associated with
/// [serverInfoFile], and returns a [CompileResult] on success.
///
/// Throws a [CompileException] if compilation fails.
/// Throws a [FileSystemException] if [serverInfoFile] cannot be accessed.
Future<CompileResult> invokeCompile({
required String executable,
required String outputDill,
required File serverInfoFile,
}) async {
final Map<String, Object?> response = await sendAndReceiveResponse(
jsonEncode({
'command': 'compile',
'executable': executable,
'output-dill': outputDill,
'useCachedCompilerOptionsAsBase': true,
}),
serverInfoFile,
);
if (response['success'] != true) {
final String errorMessage = switch (response) {
{'errorMessage': final String errorMessage} => errorMessage,
{'compilerOutputLines': final List<Object?> lines} => lines.join('\n'),
_ => 'Unknown error: $response',
};
throw new CompileException(errorMessage);
}
return new CompileResult(
outputDill: response['output-dill'] as String,
errorCount: response['errorCount'] as int,
compilerOutputLines:
(response['compilerOutputLines'] as List<Object?>?)?.cast<String>() ??
const [],
);
}
/// Sends a 'compileExpression' request to the resident frontend compiler
/// associated with [serverInfoFile], and returns a [CompileExpressionResult]
/// on success.
///
/// Throws a [CompileException] if compilation fails.
/// Throws a [FileSystemException] if [serverInfoFile] cannot be accessed.
Future<CompileExpressionResult> invokeCompileExpression({
required String expression,
required List<String> definitions,
required List<String> definitionTypes,
required List<String> typeDefinitions,
required List<String> typeBounds,
required List<String> typeDefaults,
required String libraryUri,
required String? klass,
required String? method,
required int offset,
required String? scriptUri,
required bool isStatic,
required File serverInfoFile,
}) async {
final Map<String, Object?> response = await sendAndReceiveResponse(
jsonEncode({
'command': 'compileExpression',
'expression': expression,
'definitions': definitions,
'definitionTypes': definitionTypes,
'typeDefinitions': typeDefinitions,
'typeBounds': typeBounds,
'typeDefaults': typeDefaults,
'libraryUri': libraryUri,
if (klass != null) 'class': klass,
if (method != null) 'method': method,
'offset': offset,
if (scriptUri != null) 'scriptUri': scriptUri,
'isStatic': isStatic,
'useCachedCompilerOptionsAsBase': true,
}),
serverInfoFile,
);
if (response['success'] != true) {
final String errorMessage = switch (response) {
{'errorMessage': final String errorMessage} => errorMessage,
{'compilerOutputLines': final List<Object?> lines} => lines.join('\n'),
_ => 'Unknown error: $response',
};
throw new CompileException(errorMessage);
}
return new CompileExpressionResult(
kernelBytes: response['kernelBytes'] as String,
errorCount: response['errorCount'] as int,
compilerOutputLines:
(response['compilerOutputLines'] as List<Object?>?)?.cast<String>() ??
const [],
);
}
@@ -2,6 +2,7 @@
// 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:async';
import 'dart:developer' show debugger;
import 'dart:io' show Directory, File;
import 'dart:isolate' as i;
@@ -23,13 +24,17 @@ const LINE_A = 77;
const _v0Contents = '''
import 'dart:developer';
import 'dart:isolate';
void f() {}
void f() {
print('V0.a');
}
void main() {
print('READY');
// Keep the isolate alive.
RawReceivePort();
debugger();
f();
f();
}
''';
@@ -44,10 +49,7 @@ void f() {
})();
}
void main() {
f();
f();
}
void main() {}
''';
const _v2Contents = '''
@@ -56,24 +58,22 @@ import 'dart:developer';
void f() {
(() {
print('v2.a');
print('v2.b');
(() {
print('v2.b');
})();
})();
}
void main() {
f();
f();
}
void main() {}
''';
Future<void> testeeMain() async {
// Spawn the child isolate.
final tempDir = Directory.systemTemp.createTempSync();
try {
final rootLib = File(join(tempDir.path, 'main.dart'));
rootLib.writeAsStringSync(_v0Contents);
await i.Isolate.spawnUri(rootLib.uri, [], null);
await i.Isolate.spawnUri(rootLib.uri, [], null, debugName: 'Test Main');
debugger(); // LINE_A
tempDir.deleteSync(recursive: true);
} catch (_) {
@@ -83,8 +83,6 @@ Future<void> testeeMain() async {
}
final breakpointResolutionAfterReloadingTests = <IsolateTest>[
// Ensure that the main isolate has stopped at the [debugger] statement at the
// end of [testeeMain].
hasStoppedAtBreakpoint,
stoppedAtLine(LINE_A),
(VmService service, IsolateRef isolateRef) async {
@@ -100,13 +98,16 @@ final breakpointResolutionAfterReloadingTests = <IsolateTest>[
// Find the spawned isolate.
final vm = await service.getVM();
final isolates = vm.isolates!;
expect(isolates.length, 2);
final spawnedIsolateRef = isolates.firstWhere(
(i) => i != isolateRef,
);
final spawnedIsolateRef =
isolates.firstWhere((i) => i.name == 'Test Main');
final spawnedIsolateId = spawnedIsolateRef.id!;
// Load [v1Contents] into the spawned isolate.
// Wait for spawned isolate to hit its debugger()
await hasStoppedAtBreakpoint(service, spawnedIsolateRef);
// Resume it so it finishes main() and sits idle.
await resumeIsolate(service, spawnedIsolateRef);
// --- STEP 1: RELOAD V1 ---
spawnedIsolateRootLib.writeAsStringSync(_v1Contents);
await service.reloadSources(
spawnedIsolateId,
@@ -121,16 +122,23 @@ final breakpointResolutionAfterReloadingTests = <IsolateTest>[
) as Library;
String scriptId = rootLib.scripts![0].id!;
// Add a breakpoint at `print('v1');`.
await service.addBreakpoint(spawnedIsolateId, scriptId, 6);
// Add a breakpoint at `print('v1');` (line 6 of v1).
final Breakpoint bpt1 =
await service.addBreakpoint(spawnedIsolateId, scriptId, 6);
// Trigger f() in the reloaded code.
// This ensures a fresh entry into the reloaded f().
print('Invoking f() V1');
unawaited(service.invoke(spawnedIsolateId, rootLib.id!, 'f', []));
// Resuming the spawned isolate should let it run until it gets paused at
// the breakpoint at `print('v1');`.
await resumeIsolate(service, spawnedIsolateRef);
await hasStoppedAtBreakpoint(service, spawnedIsolateRef);
await stoppedAtLine(6)(service, spawnedIsolateRef);
// Load [v2Contents] into the spawned isolate.
// Remove the breakpoint before moving to V2.
await service.removeBreakpoint(spawnedIsolateId, bpt1.id!);
await resumeIsolate(service, spawnedIsolateRef);
// --- STEP 2: RELOAD V2 ---
spawnedIsolateRootLib.writeAsStringSync(_v2Contents);
await service.reloadSources(
spawnedIsolateId,
@@ -145,27 +153,25 @@ final breakpointResolutionAfterReloadingTests = <IsolateTest>[
) as Library;
scriptId = rootLib.scripts![0].id!;
// Add a breakpoint at `print('v2.a');`.
await service.addBreakpoint(spawnedIsolateId, scriptId, 5);
// Add a breakpoint at `print('v2.a');` (line 5 of v2).
final Breakpoint bpt2 =
await service.addBreakpoint(spawnedIsolateId, scriptId, 5);
print('Invoking f() V2');
unawaited(service.invoke(spawnedIsolateId, rootLib.id!, 'f', []));
// Resuming the spawned isolate should let it run until it gets paused at
// the breakpoint at `print('v2.a');`.
await resumeIsolate(service, spawnedIsolateRef);
await hasStoppedAtBreakpoint(service, spawnedIsolateRef);
await stoppedAtLine(5)(service, spawnedIsolateRef);
// Add a breakpoint at `print('v2.b');`.
final breakpoint3 =
await service.addBreakpoint(spawnedIsolateId, scriptId, 6);
expect(breakpoint3.breakpointNumber, 3);
// We previously had a bug that would have made the breakpoint resolution
// code get confused by the old closure that was defined in [v1Contents].
// We prevent a reintroduction of that bug by ensuring that the newly set
// breakpoint has been resolved immediately.
expect(breakpoint3.resolved, true);
// Remove the breakpoint.
await service.removeBreakpoint(spawnedIsolateId, bpt2.id!);
await resumeIsolate(service, spawnedIsolateRef);
// Add a breakpoint at `print('v2.b');` (line 6 of v2).
final bpt = await service.addBreakpoint(spawnedIsolateId, scriptId, 6);
expect(bpt.resolved, true);
// No need for final resume as the isolate is already running and idle.
tempDir.deleteSync(recursive: true);
} catch (_) {
tempDir.deleteSync(recursive: true);
+6 -4
View File
@@ -284,10 +284,12 @@ class _ServiceTesteeLauncher {
}
}
void setupAddresses(Uri /*!*/ serverAddress) {
serviceWebsocketAddress =
'ws://${serverAddress.authority}${serverAddress.path}ws';
serviceHttpAddress = 'http://${serverAddress.authority}${serverAddress.path}';
void setupAddresses(Uri serverAddress) {
serviceWebsocketAddress = serverAddress.replace(
scheme: 'ws',
pathSegments: [...serverAddress.pathSegments, 'ws'],
).toString();
serviceHttpAddress = serverAddress.replace(scheme: 'http').toString();
}
class _ServiceTesterRunner {
+8
View File
@@ -220,6 +220,11 @@ bool Options::ParseDartDevArguments(int argc,
skipVmOption = true;
} else if (IsOption(argv[i], "enable-experiment")) {
dart_options->AddArgument(argv[i]);
} else if (IsOption(argv[i], "resident")) {
resident_ = true;
} else if (IsOption(argv[i], "resident-compiler-info-file")) {
resident_compiler_info_file_path_ = OptionProcessor::ProcessOption(
argv[i], "--resident-compiler-info-file");
}
}
if (!skipVmOption) {
@@ -346,6 +351,9 @@ void Options::PrintUsage() {
}
// clang-format on
bool Options::resident_ = false;
const char* Options::resident_compiler_info_file_path_ = nullptr;
dart::SimpleHashMap* Options::environment_ = nullptr;
bool Options::ProcessEnvironmentOption(const char* arg,
CommandLineOptions* vm_options) {
+8
View File
@@ -76,6 +76,11 @@ class Options {
SHORT_BOOL_OPTIONS_LIST(SHORT_BOOL_OPTION_GETTER)
#undef SHORT_BOOL_OPTION_GETTER
static bool resident() { return resident_; }
static const char* resident_compiler_info_file_path() {
return resident_compiler_info_file_path_;
}
// Callbacks have to be public.
#define CB_OPTIONS_DECL(callback) \
static bool callback(const char* arg, CommandLineOptions* vm_options);
@@ -113,6 +118,9 @@ class Options {
SHORT_BOOL_OPTIONS_LIST(SHORT_BOOL_OPTION_DECL)
#undef SHORT_BOOL_OPTION_DECL
static bool resident_;
static const char* resident_compiler_info_file_path_;
static dart::SimpleHashMap* environment_;
static char** env_argv_;
-2
View File
@@ -4010,8 +4010,6 @@ static void ReloadKernel(Thread* thread, JSONStream* js) {
isolate_group->ReloadKernel(js, force_reload, kernel_buffer,
kernel_buffer_size);
free(kernel_buffer);
Service::CheckForPause(isolate, js);
#endif // defined(DART_PRECOMPILED_RUNTIME)
}