// Copyright (c) 2020, 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.

/// This command allows to inspect information written into the
/// precompiler trace (`--trace-precompiler-to` output).
library vm_snapshot_analysis.explain;

import 'dart:async';
import 'dart:io';
import 'dart:math' as math;

import 'package:args/command_runner.dart';

import 'package:vm_snapshot_analysis/name.dart';
import 'package:vm_snapshot_analysis/precompiler_trace.dart';
import 'package:vm_snapshot_analysis/program_info.dart';
import 'package:vm_snapshot_analysis/utils.dart';

import 'utils.dart';

class ExplainCommand extends Command<void> {
  @override
  final name = 'explain';

  @override
  final description = '''
Explain why certain methods were pulled into the binary.
''';

  ExplainCommand() {
    addSubcommand(ExplainDynamicCallsCommand());
  }
}

/// Generates a summary report about dynamic calls sorted by approximation
/// of their retained size, i.e. the amount of bytes these calls are pulling
/// into the snapshot.
class ExplainDynamicCallsCommand extends Command<void> {
  @override
  final name = 'dynamic-calls';

  @override
  final description = '''
This command explains impact of the dynamic calls on the binary size.

It needs AOT snapshot size profile (an output of either
--write-v8-snapshot-profile-to or --print-instructions-sizes-to flags) and
precompiler trace (an output of --trace-precompiler-to flag).
''';

  ExplainCommand() {}

  @override
  Future<void> run() async {
    final sizesJson = File(argResults.rest[0]);
    if (!sizesJson.existsSync()) {
      usageException('Size profile ${sizesJson.path} does not exist!');
    }
    final sizesJsonRaw = await loadJsonFromFile(sizesJson);

    final traceJson = File(argResults.rest[1]);
    if (!traceJson.existsSync()) {
      usageException('Size profile ${traceJson.path} does not exist!');
    }
    final traceJsonRaw = await loadJsonFromFile(traceJson);

    final callGraph = loadTrace(traceJsonRaw);
    callGraph.computeDominators();

    final programInfo = loadProgramInfoFromJson(sizesJsonRaw);

    final histogram = Histogram.fromIterable<CallGraphNode>(
        callGraph.dynamicCalls, sizeOf: (dynamicCall) {
      // Compute approximate retained size by traversing the dominator tree
      // and consulting snapshot profile.
      var totalSize = 0;
      dynamicCall.visitDominatorTree((retained, depth) {
        if (retained.isFunctionNode) {
          // Note that call graph keeps private library keys intact in the
          // names (because we need to distinguish dynamic invocations
          // through with the same private name in different libraries).
          // So we need to scrub the path before we lookup information in the
          // profile.
          final path = (retained.data as ProgramInfoNode)
              .path
              .map((n) => Name(n).scrubbed)
              .toList();
          if (path.last.startsWith('[tear-off] ')) {
            // Tear-off forwarder is placed into the function that is torn so
            // we need to slightly tweak the path to be able to find it.
            path.insert(
                path.length - 1, path.last.replaceAll('[tear-off] ', ''));
          }
          final retainedSize = programInfo.lookup(path);
          totalSize += (retainedSize?.totalSize ?? 0);
        }
        return true;
      });
      return totalSize;
    }, bucketFor: (n) {
      return (n.data as String).replaceAll('dyn:', '');
    }, bucketInfo: BucketInfo(nameComponents: ['Selector']));

    printHistogram(programInfo, histogram,
        prefix: histogram.bySize.where((key) => histogram.buckets[key] > 0));

    // For top 10 dynamic selectors print the functions which contain these
    // dynamic calls.
    for (var selector
        in histogram.bySize.take(math.min(10, histogram.length))) {
      final dynSelector = 'dyn:$selector';
      final callNodes = callGraph.nodes
          .where((n) => n.data == selector || n.data == dynSelector);

      print('\nDynamic call to ${selector}'
          ' (retaining ~${histogram.buckets[selector]} bytes) occurs in:');
      for (var node in callNodes) {
        for (var pred in node.pred) {
          print('    ${pred.data.qualifiedName}');
        }
      }
    }
  }

  @override
  String get invocation =>
      super.invocation.replaceAll('[arguments]', '<sizes.json> <trace.json>');
}
