| // 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. | 
 |  | 
 | // @dart=2.9 | 
 |  | 
 | import 'dart:convert'; | 
 | import 'dart:io'; | 
 |  | 
 | import 'package:compiler/src/dart2js.dart' as dart2js; | 
 |  | 
 | Future<void> main(List<String> args) async { | 
 |   if (args.contains('--child')) { | 
 |     return; | 
 |   } | 
 |  | 
 |   // Include dart2js and prevent tree-shaking to make this program have a | 
 |   // non-trival snapshot size. | 
 |   if (args.contains('--train')) { | 
 |     args.remove('--train'); | 
 |     return dart2js.main(args); | 
 |   } | 
 |  | 
 |   var tempDir; | 
 |   var events; | 
 |   try { | 
 |     tempDir = await Directory.systemTemp.createTemp(); | 
 |     final timelinePath = | 
 |         tempDir.uri.resolve('Startup-timeline.json').toFilePath(); | 
 |     final p = await Process.run(Platform.executable, [ | 
 |       ...Platform.executableArguments, | 
 |       '--timeline_recorder=file:$timelinePath', | 
 |       '--timeline_streams=VM,Isolate,Embedder', | 
 |       Platform.script.toFilePath(), | 
 |       '--child' | 
 |     ]); | 
 |     if (p.exitCode != 0) { | 
 |       print(p.stdout); | 
 |       print(p.stderr); | 
 |       throw 'Child process failed: ${p.exitCode}'; | 
 |     } | 
 |  | 
 |     events = jsonDecode(await File(timelinePath).readAsString()); | 
 |   } finally { | 
 |     await tempDir.delete(recursive: true); | 
 |   } | 
 |  | 
 |   var mainIsolateId; | 
 |   for (final event in events) { | 
 |     if (event['name'] == 'InitializeIsolate' && | 
 |         event['args']['isolateName'] == 'main') { | 
 |       mainIsolateId = event['args']['isolateId']; | 
 |     } | 
 |   } | 
 |   if (mainIsolateId == null) { | 
 |     throw 'Could not determine main isolate'; | 
 |   } | 
 |  | 
 |   void report(String name, String isolateId) { | 
 |     var filtered = events.where((event) => event['name'] == name); | 
 |     if (isolateId != null) { | 
 |       filtered = | 
 |           filtered.where((event) => event['args']['isolateId'] == isolateId); | 
 |     } | 
 |     var micros; | 
 |     final durations = filtered.where((event) => event['ph'] == 'X'); | 
 |     final begins = filtered.where((event) => event['ph'] == 'B'); | 
 |     final ends = filtered.where((event) => event['ph'] == 'E'); | 
 |     if (durations.length == 1 && begins.length == 0 && ends.length == 0) { | 
 |       micros = durations.single['dur']; | 
 |     } else if (durations.length == 0 && | 
 |         begins.length == 1 && | 
 |         ends.length == 1) { | 
 |       micros = ends.single['ts'] - begins.single['ts']; | 
 |     } else { | 
 |       print(durations.toList()); | 
 |       print(begins.toList()); | 
 |       print(ends.toList()); | 
 |       throw '$name is missing or ambiguous'; | 
 |     } | 
 |     print('Startup.$name(StartupTime): $micros us.'); | 
 |   } | 
 |  | 
 |   report('CreateIsolateGroupAndSetupHelper', null); | 
 |   report('InitializeIsolate', mainIsolateId); | 
 |   report('ReadProgramSnapshot', mainIsolateId); | 
 | } |