// Copyright (c) 2013, 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 '../inferrer/abstract_value_domain.dart';
import '../js_backend/field_analysis.dart' show JFieldAnalysis;
import '../js_model/elements.dart' show JField;
import '../js_model/js_world.dart' show JClosedWorld;
import 'logging.dart';
import 'nodes.dart';
import 'optimize.dart' show OptimizationPhase;

/// Optimization phase that tries to eliminate late field checks and memory
/// loads.
class SsaLateFieldOptimizer extends HBaseVisitor<void>
    implements OptimizationPhase {
  @override
  final String name = "SsaLateFieldOptimizer";

  final JClosedWorld _closedWorld;
  final OptimizationTestLog? _log;

  final AbstractValueDomain _abstractValueDomain;
  final JFieldAnalysis _fieldAnalysis;

  SsaLateFieldOptimizer(this._closedWorld, this._log)
      : _abstractValueDomain = _closedWorld.abstractValueDomain,
        _fieldAnalysis = _closedWorld.fieldAnalysis;

  @override
  void visitGraph(HGraph graph) {
    _log?.instructionHistogram('$name.pre', graph, _summarizeInstruction);

    visitDominatorTree(graph);

    _log?.instructionHistogram('$name.post', graph, _summarizeInstruction);
  }

  static String? _summarizeInstruction(HInstruction node) {
    if (node is HLateCheck) return '${node.runtimeType}';
    if (node is HFieldGet) return '${node.runtimeType}';
    return null;
  }

  @override
  bool validPostcondition(HGraph graph) => true;

  @override
  void visitBasicBlock(HBasicBlock block) {
    HInstruction? instruction = block.first;
    while (instruction != null) {
      HInstruction? next = instruction.next;
      instruction.accept(this);
      instruction = next;
    }
  }

  @override
  void visitLateReadCheck(HLateReadCheck node) {
    // The getter for a `late` instance field has a check on the backing field
    // to ensure that the sentinel value has been overwritten by an initializing
    // assignment. When the getter is inlined, there is a sequence of loads,
    // each with a check. `h(g(a.f), g(a.f))` looks like the following, where
    // `#f` is the backing field for late field `f`.
    //
    //     t1 = HFieldGet(a, #f)       {T,sentinel}
    //     t2 = HLateReadCheck(t1)     {T}
    //     t9 = g(t2)
    //     t11 = HFieldGet(a, #f)      {T,sentinel}
    //     t12 = HLateReadCheck(t11)   {T}
    //     t19 = g(t12)
    //     t99 = h(t9, t19)
    //
    // The field starts initialized with a sentinel value. HLateReadCheck will
    // throw if the value is a sentinel.  The backing field is never assigned a
    // sentinel, so subsequent read checks will always succeed and can be
    // removed.
    //
    // ## `late` fields
    //
    // The removal is effected by marking the subsequent loaded values with a
    // strengthened type that excludes the sentinel, using HTypeKnown. This
    // makes the sentinel check redundant so it can be removed when it is
    // visited later in the pass.
    //
    // To prevent _uses_ of the loaded values from being moved to before the
    // check, HTypeKnown is witnessed by (has a dependency on) the original
    // check. We know the value is not a sentinel only _after_ the check.
    // (Optimizations preserve the order of loads and stores. It is fine for the
    // second load to move before the first check provided doing so does not
    // change the value seen by the second load.)
    //
    // After inserting the HTypeKnown.witnessed instruction after each
    // subsequent load we have:
    //
    //     t1 = HFieldGet(a, #f)       {T,sentinel}
    //     t2 = HLateReadCheck(t1)     {T}
    //     t9 = g(t2)
    //     t11 = HFieldGet(a, #f)      {T,sentinel}
    //     t12 = HTypeKnown(t11, t2)   {T}
    //     t13 = HLateReadCheck(t12)   {T}
    //     t19 = g(t13)
    //     t99 = h(t9, t19)
    //
    // The subsequent checks are now redundant, and are visited after the
    // initial check, so they are cleaned up when visited.
    //
    //     t1 = HFieldGet(a, #f)       {T,sentinel}
    //     t2 = HLateReadCheck(t1)     {T}
    //     t9 = g(t2)
    //     t11 = HFieldGet(a, #f)      {T,sentinel}
    //     t12 = HTypeKnown(t11, t2)   {T}
    //     t19 = g(t12)
    //     t99 = h(t9, t19)
    //
    // ## `late final` fields
    //
    // `late final` fields change value only once from sentinel to final value.
    // If the read-check passes, the value is the final value, so the subsequent
    // reads can be replaced by the checked value:
    //
    //     t1 = HFieldGet(a, #f)       {T,sentinel}
    //     t2 = HLateReadCheck(t1)     {T}
    //     t9 = g(t2)
    //     t12 = HLateReadCheck(t2)   {T}
    //     t19 = g(t12)
    //     t99 = h(t9, t19)
    //
    // This leads to back-to-back HLateReadCheck instructions, the second of
    // which is redundant and is removed:
    //
    //     t1 = HFieldGet(a, #f)       {T,sentinel}
    //     t2 = HLateReadCheck(t1)     {T}
    //     t9 = g(t2)
    //     t19 = g(t2)
    //     t99 = h(t9, t19)

    HInstruction input = node.checkedInput;

    // Cleanup. Remove redundant checks.
    if (input is HLateReadCheck || node.isRedundant(_closedWorld)) {
      node.block!.rewrite(node, input);
      node.block!.remove(node);
      return;
    }

    if (input is HFieldGet) {
      HInstruction receiver = input.receiver;
      final field = input.element as JField;

      final uses = DominatedUses.of(receiver, node);

      List<HFieldGet> loads = [];
      for (HInstruction use in uses.instructions) {
        if (use is HFieldGet && use.element == field) {
          loads.add(use);
        }
      }

      if (loads.isEmpty) return;

      if (_fieldAnalysis.getFieldData(field).isAssignedOnce) {
        // `late final` backing fields are assigned at most once, so loads can
        // be replaced with the dominating checked load value.
        for (final load in loads) {
          load.block!.rewrite(load, node);
          load.block!.remove(load);
        }
      } else {
        for (final load in loads) {
          final known = HTypeKnown.witnessed(node.instructionType, load, node)
            ..sourceInformation = node.sourceInformation;
          load.block!.rewrite(load, known);
          load.block!.addAfter(load, known);
        }
      }
    }
  }

  @override
  void visitFieldSet(HFieldSet node) {
    final field = node.element as JField;
    final fieldData = _fieldAnalysis.getFieldData(field);
    if (!fieldData.isLateBackingField) return;

    // [node] is a store to the backing field for a late instance field. The
    // stored value cannot be the sentinel value, so future loads of the field
    // will never be the sentinel value and do not need to be checked.
    final uses = DominatedUses.of(node.receiver, node, excludeDominator: true);

    List<HFieldGet> loads = [];
    for (HInstruction use in uses.instructions) {
      if (use is HFieldGet && use.element == field) {
        loads.add(use);
      }
    }

    if (loads.isEmpty) return;

    if (fieldData.isAssignedOnce) {
      // [field] is a `late final` field so the stored value is the value of
      // every subsequent load. Replace loads with the stored value.
      for (final load in loads) {
        load.block!.rewrite(load, node.value);
        load.block!.remove(load);
      }
    } else {
      // The subsequent loaded value cannot be the sentinel value. Refine the
      // type of the load which will allow any check on the load to be removed.
      // There is no need for HTypeKnown.witnessed since it would be an invalid
      // transformation to move the read before the write.
      for (final load in loads) {
        load.instructionType =
            _abstractValueDomain.excludeLateSentinel(load.instructionType);
      }
    }
  }
}
