927c59104f
Fixes the case where the Image name and type was not written to the v8 snapshot profile in non-precompiled mode. Adds core-jit snapshot tests to the v8 snapshot profile writer test. In core-jit and app-aot-elf modes, verify that all bytes in the snapshot sections are accounted for in the profile. Bug: https://github.com/dart-lang/sdk/issues/45787 TEST=vm/dart{,_2}/v8_snapshot_profile_writer_test Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-debug-x64-try Change-Id: I88be309cdea6293d768e2fa458492387d70fde22 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/196323 Commit-Queue: Tess Strickland <sstrickl@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Daco Harkes <dacoharkes@google.com>
193 lines
5.9 KiB
Dart
193 lines
5.9 KiB
Dart
// Copyright (c) 2019, 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';
|
|
|
|
import 'package:expect/expect.dart';
|
|
import 'package:path/path.dart' as path;
|
|
|
|
final isAOTRuntime = path.basenameWithoutExtension(Platform.executable) ==
|
|
'dart_precompiled_runtime';
|
|
final buildDir = path.dirname(Platform.executable);
|
|
final sdkDir = path.dirname(path.dirname(buildDir));
|
|
final platformDill = path.join(buildDir, 'vm_platform_strong.dill');
|
|
final genKernel = path.join(sdkDir, 'pkg', 'vm', 'tool',
|
|
'gen_kernel' + (Platform.isWindows ? '.bat' : ''));
|
|
final _genSnapshotBase = 'gen_snapshot' + (Platform.isWindows ? '.exe' : '');
|
|
// Slight hack to work around issue that gen_snapshot for simarm_x64 is not
|
|
// in the same subdirectory as dart_precompiled_runtime (${MODE}SIMARM), but
|
|
// instead it's in ${MODE}SIMARM_X64.
|
|
final genSnapshot = File(path.join(buildDir, _genSnapshotBase)).existsSync()
|
|
? path.join(buildDir, _genSnapshotBase)
|
|
: path.join(buildDir + '_X64', _genSnapshotBase);
|
|
final aotRuntime = path.join(
|
|
buildDir, 'dart_precompiled_runtime' + (Platform.isWindows ? '.exe' : ''));
|
|
|
|
String? get clangBuildToolsDir {
|
|
String archDir;
|
|
if (Platform.isLinux) {
|
|
archDir = 'linux-x64';
|
|
} else if (Platform.isMacOS) {
|
|
archDir = 'mac-x64';
|
|
} else {
|
|
return null;
|
|
}
|
|
var clangDir = path.join(sdkDir, 'buildtools', archDir, 'clang', 'bin');
|
|
return Directory(clangDir).existsSync() ? clangDir : null;
|
|
}
|
|
|
|
Future<void> assembleSnapshot(String assemblyPath, String snapshotPath) async {
|
|
if (!Platform.isLinux && !Platform.isMacOS) {
|
|
throw "Unsupported platform ${Platform.operatingSystem} for assembling";
|
|
}
|
|
|
|
final ccFlags = <String>[];
|
|
final ldFlags = <String>[];
|
|
String cc = 'gcc';
|
|
String shared = '-shared';
|
|
|
|
if (Platform.isMacOS) {
|
|
cc = 'clang';
|
|
} else if (buildDir.endsWith('SIMARM') || buildDir.endsWith('SIMARM64')) {
|
|
final clangBuildTools = clangBuildToolsDir;
|
|
if (clangBuildTools != null) {
|
|
cc = path.join(clangBuildTools, 'clang');
|
|
} else {
|
|
throw 'Cannot assemble for ${path.basename(buildDir)} '
|
|
'without //buildtools on ${Platform.operatingSystem}';
|
|
}
|
|
}
|
|
|
|
if (Platform.isMacOS) {
|
|
shared = '-dynamiclib';
|
|
// Tell Mac linker to give up generating eh_frame from dwarf.
|
|
ldFlags.add('-Wl,-no_compact_unwind');
|
|
} else if (buildDir.endsWith('SIMARM')) {
|
|
ccFlags.add('--target=armv7-linux-gnueabihf');
|
|
} else if (buildDir.endsWith('SIMARM64')) {
|
|
ccFlags.add('--target=aarch64-linux-gnu');
|
|
}
|
|
|
|
if (buildDir.endsWith('X64') || buildDir.endsWith('SIMARM64')) {
|
|
ccFlags.add('-m64');
|
|
}
|
|
|
|
await run(cc, <String>[
|
|
...ccFlags,
|
|
...ldFlags,
|
|
shared,
|
|
'-nostdlib',
|
|
'-o',
|
|
snapshotPath,
|
|
assemblyPath,
|
|
]);
|
|
}
|
|
|
|
Future<void> stripSnapshot(String snapshotPath, String strippedPath,
|
|
{bool forceElf = false}) async {
|
|
if (!Platform.isLinux && !Platform.isMacOS) {
|
|
throw "Unsupported platform ${Platform.operatingSystem} for stripping";
|
|
}
|
|
|
|
var strip = 'strip';
|
|
|
|
if ((Platform.isLinux &&
|
|
(buildDir.endsWith('SIMARM') || buildDir.endsWith('SIMARM64'))) ||
|
|
(Platform.isMacOS && forceElf)) {
|
|
final clangBuildTools = clangBuildToolsDir;
|
|
if (clangBuildTools != null) {
|
|
strip = path.join(clangBuildTools, 'llvm-strip');
|
|
} else {
|
|
throw 'Cannot strip ELF files for ${path.basename(buildDir)} '
|
|
'without //buildtools on ${Platform.operatingSystem}';
|
|
}
|
|
}
|
|
|
|
await run(strip, <String>[
|
|
'-o',
|
|
strippedPath,
|
|
snapshotPath,
|
|
]);
|
|
}
|
|
|
|
Future<ProcessResult> runHelper(String executable, List<String> args) async {
|
|
print('Running $executable ${args.join(' ')}');
|
|
|
|
final result = await Process.run(executable, args);
|
|
print('Subcommand terminated with exit code ${result.exitCode}.');
|
|
if (result.stdout.isNotEmpty) {
|
|
print('Subcommand stdout:');
|
|
print(result.stdout);
|
|
}
|
|
if (result.exitCode != 0) {
|
|
if (result.stderr.isNotEmpty) {
|
|
print('Subcommand stderr:');
|
|
print(result.stderr);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
Future<bool> testExecutable(String executable) async {
|
|
try {
|
|
final result = await runHelper(executable, <String>['--version']);
|
|
return result.exitCode == 0;
|
|
} on ProcessException catch (e) {
|
|
print('Got process exception: $e');
|
|
return false;
|
|
}
|
|
}
|
|
|
|
Future<void> run(String executable, List<String> args) async {
|
|
final result = await runHelper(executable, args);
|
|
|
|
if (result.exitCode != 0) {
|
|
throw 'Command failed with unexpected exit code (was ${result.exitCode})';
|
|
}
|
|
}
|
|
|
|
Future<List<String>> runOutput(String executable, List<String> args) async {
|
|
final result = await runHelper(executable, args);
|
|
|
|
if (result.exitCode != 0) {
|
|
throw 'Command failed with unexpected exit code (was ${result.exitCode})';
|
|
}
|
|
Expect.isTrue(result.stdout.isNotEmpty);
|
|
Expect.isTrue(result.stderr.isEmpty);
|
|
|
|
return await Stream.value(result.stdout as String)
|
|
.transform(const LineSplitter())
|
|
.toList();
|
|
}
|
|
|
|
Future<List<String>> runError(String executable, List<String> args) async {
|
|
final result = await runHelper(executable, args);
|
|
|
|
if (result.exitCode == 0) {
|
|
throw 'Command did not fail with non-zero exit code';
|
|
}
|
|
Expect.isTrue(result.stdout.isEmpty);
|
|
Expect.isTrue(result.stderr.isNotEmpty);
|
|
|
|
return await Stream.value(result.stderr as String)
|
|
.transform(const LineSplitter())
|
|
.toList();
|
|
}
|
|
|
|
const keepTempKey = 'KEEP_TEMPORARY_DIRECTORIES';
|
|
|
|
Future<void> withTempDir(String name, Future<void> fun(String dir)) async {
|
|
final tempDir = Directory.systemTemp.createTempSync(name);
|
|
try {
|
|
await fun(tempDir.path);
|
|
} finally {
|
|
if (!Platform.environment.containsKey(keepTempKey) ||
|
|
Platform.environment[keepTempKey]!.isEmpty) {
|
|
tempDir.deleteSync(recursive: true);
|
|
}
|
|
}
|
|
}
|