9d2f622f38
Fixes: https://github.com/dart-lang/sdk/issues/56865 Change-Id: I1a88ba40351ed1b42bb1a800b384a00eb7548225 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/418740 Commit-Queue: Derek Xu <derekx@google.com> Reviewed-by: Ben Konyi <bkonyi@google.com>
174 lines
5.4 KiB
Dart
174 lines
5.4 KiB
Dart
// Copyright (c) 2022, 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:convert';
|
|
import 'dart:io' show File, FileSystemException;
|
|
import 'dart:vmservice_io' show getResidentCompilerInfoFileConsideringArgsImpl;
|
|
|
|
import 'package:args/args.dart';
|
|
import 'package:frontend_server/resident_frontend_server_utils.dart'
|
|
show sendAndReceiveResponse;
|
|
import 'package:path/path.dart' as p;
|
|
|
|
import 'commands/compilation_server.dart' show CompilationServerCommand;
|
|
import 'resident_frontend_constants.dart';
|
|
|
|
/// The Resident Frontend Compiler's shutdown command.
|
|
final residentServerShutdownCommand = jsonEncode(
|
|
<String, Object>{
|
|
commandString: shutdownString,
|
|
},
|
|
);
|
|
|
|
File? getResidentCompilerInfoFileConsideringArgs(final ArgResults args) =>
|
|
getResidentCompilerInfoFileConsideringArgsImpl(
|
|
args[CompilationServerCommand.residentCompilerInfoFileFlag] ??
|
|
args[CompilationServerCommand.legacyResidentServerInfoFileFlag]);
|
|
|
|
final String packageConfigName = p.join('.dart_tool', 'package_config.json');
|
|
|
|
/// Removes the [serverInfoFile].
|
|
void cleanupResidentServerInfo(File serverInfoFile) {
|
|
if (serverInfoFile.existsSync()) {
|
|
try {
|
|
serverInfoFile.deleteSync();
|
|
} catch (_) {}
|
|
}
|
|
}
|
|
|
|
/// First, attempts to shut down the Resident Frontend Compiler associated with
|
|
/// [infoFile]. If successful, [infoFile] is deleted. If any error occurs
|
|
/// preventing shutdown, the error is ignored and [infoFile] is deleted, making
|
|
/// the compiler be forgetten. The forgotten compiler will shut itself down a
|
|
/// certain period of inactivity (see the inactivityTimeout parameter of
|
|
/// residentListenAndCompile in
|
|
/// pkg/frontend_server/lib/src/resident_frontend_server.dart).
|
|
Future<void> shutDownOrForgetResidentFrontendCompiler(File infoFile) async {
|
|
try {
|
|
// As explained in the doc comment above, this function ignores errors. So,
|
|
// we ignore the return value of [sendAndReceiveResponse].
|
|
await sendAndReceiveResponse(
|
|
residentServerShutdownCommand,
|
|
infoFile,
|
|
);
|
|
} on FileSystemException catch (_) {
|
|
// As explained in the doc comment above, this function ignores errors. We
|
|
// only catch [FileSystemException]s because [sendAndReceiveResponse] cannot
|
|
// throw any other type of error.
|
|
}
|
|
cleanupResidentServerInfo(infoFile);
|
|
}
|
|
|
|
Future<bool> isFileKernelFile(final File file) async {
|
|
final bytes = await file.openRead(0, 4).expand((i) => i).toList();
|
|
if (bytes.length < 4) {
|
|
return false;
|
|
}
|
|
// Check for the magic number at the start of kernel files.
|
|
return bytes[0] == 0x90 &&
|
|
bytes[1] == 0xab &&
|
|
bytes[2] == 0xcd &&
|
|
bytes[3] == 0xef;
|
|
}
|
|
|
|
Future<bool> isFileAppJitSnapshot(final File file) async {
|
|
final bytes = await file.openRead(0, 8).expand((i) => i).toList();
|
|
if (bytes.length < 8) {
|
|
return false;
|
|
}
|
|
// Check for the magic number at the start of AppJIT snapshots.
|
|
return bytes[0] == 0xdc &&
|
|
bytes[1] == 0xdc &&
|
|
bytes[2] == 0xf6 &&
|
|
bytes[3] == 0xf6 &&
|
|
bytes[4] == 0 &&
|
|
bytes[5] == 0 &&
|
|
bytes[6] == 0 &&
|
|
bytes[7] == 0;
|
|
}
|
|
|
|
Future<bool> isFileAotSnapshot(final File file) async {
|
|
// Check for any of the magic numbers that can be found at the start of an
|
|
// AOT snapshot.
|
|
|
|
final bytes = await file.openRead(0, 4).expand((i) => i).toList();
|
|
// Check for the COFF magic numbers.
|
|
if (bytes.length < 2) {
|
|
return false;
|
|
}
|
|
if (bytes[0] == 0x01 && bytes[1] == 0xc0 || // arm32
|
|
bytes[0] == 0xaa && bytes[1] == 0x64 || // arm64
|
|
bytes[0] == 0x50 && bytes[1] == 0x32 || // riscv32
|
|
bytes[0] == 0x50 && bytes[1] == 0x64 /* riscv64 */) {
|
|
return true;
|
|
}
|
|
|
|
if (bytes.length < 4) {
|
|
return false;
|
|
}
|
|
// Check for the ELF magic number.
|
|
if (bytes[0] == 0x7f &&
|
|
bytes[1] == 0x45 &&
|
|
bytes[2] == 0x4c &&
|
|
bytes[3] == 0x46) {
|
|
return true;
|
|
}
|
|
// Check for the Mach-O magic numbers.
|
|
if (bytes[0] == 0xfe &&
|
|
bytes[1] == 0xed &&
|
|
bytes[2] == 0xfa &&
|
|
bytes[3] == 0xce) {
|
|
// macho32
|
|
return true;
|
|
}
|
|
if (bytes[0] == 0xfe &&
|
|
bytes[1] == 0xed &&
|
|
bytes[2] == 0xfa &&
|
|
bytes[3] == 0xcf) {
|
|
// macho64
|
|
return true;
|
|
}
|
|
if (bytes[0] == 0xcf &&
|
|
bytes[1] == 0xfa &&
|
|
bytes[2] == 0xed &&
|
|
bytes[3] == 0xfe) {
|
|
// macho64_arm64
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/// Used to create compile requests for the run CLI command.
|
|
///
|
|
/// Returns a JSON string that the resident compiler will be able to interpret.
|
|
String createCompileJitJson({
|
|
required String executable,
|
|
required String outputDill,
|
|
required ArgResults args,
|
|
String? packages,
|
|
bool verbose = false,
|
|
}) {
|
|
return jsonEncode(
|
|
<String, Object?>{
|
|
commandString: compileString,
|
|
sourceString: executable,
|
|
outputString: outputDill,
|
|
if (args.wasParsed(defineOption))
|
|
defineOption: args.multiOption(defineOption),
|
|
if (args.options.contains(enableAssertsOption) &&
|
|
args.wasParsed(enableAssertsOption))
|
|
enableAssertsOption: true,
|
|
if (args.wasParsed(enableExperimentOption))
|
|
enableExperimentOption: args
|
|
.multiOption(enableExperimentOption)
|
|
.map((e) => '--enable-experiment=$e')
|
|
.toList(),
|
|
if (packages != null) packageString: packages,
|
|
if (args.wasParsed(verbosityOption))
|
|
verbosityOption: args[verbosityOption],
|
|
},
|
|
);
|
|
}
|