// Copyright (c) 2016, 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.
library dart2js.cps_ir.use_field_initializers;

import 'cps_ir_nodes.dart';
import 'optimizers.dart';
import '../elements/elements.dart';
import '../js_backend/js_backend.dart';

/// Eliminates [SetField] instructions when the value can instead be passed into
/// the field initializer of a [CreateInstance] instruction.
///
/// This compensates for a somewhat common pattern where fields are initialized
/// in the constructor body instead of using initializers. For example:
///
///     class Foo {
///       var x, y;
///       Foo(x, y) {
///          this.x = x;
///          this.y = y;
///        }
///      }
///
///   ==> (IR for Foo constructor)
///
///      foo = new D.Foo(null, null);
///      foo.x = 'a';
///      foo.y = 'b';
///
///   ==> (after this pass)
///
///      foo = new D.Foo('a', 'b');
//
// TODO(asgerf): Store forwarding and load elimination could most likely
//   handle this more generally.
//
class UseFieldInitializers extends BlockVisitor implements Pass {
  String get passName => 'Use field initializers';

  final JavaScriptBackend backend;

  final Set<CreateInstance> unescaped = new Set<CreateInstance>();

  /// Continuation bindings separating the current traversal position from an
  /// unescaped [CreateInstance].  When [CreateInstance] is sunk, these
  /// continuations must sink as well to ensure the object remains in scope
  /// inside the bound continuations.
  final List<LetCont> letConts = <LetCont>[];

  /// If non-null, the bindings in [letConts] should sink to immediately below
  /// this node.
  InteriorNode letContSinkTarget = null;
  EscapeVisitor escapeVisitor;

  UseFieldInitializers(this.backend);

  void rewrite(FunctionDefinition node) {
    escapeVisitor = new EscapeVisitor(this);
    BlockVisitor.traverseInPreOrder(node, this);
  }

  void escape(Reference ref) {
    Definition def = ref.definition;
    if (def is CreateInstance) {
      unescaped.remove(def);
      if (unescaped.isEmpty) {
        sinkLetConts();
        letConts.clear();
      }
    }
  }

  void visitContinuation(Continuation node) {
    endBasicBlock();
  }
  void visitLetHandler(LetHandler node) {
    endBasicBlock();
  }
  void visitInvokeContinuation(InvokeContinuation node) {
    endBasicBlock();
  }
  void visitBranch(Branch node) {
    endBasicBlock();
  }
  void visitRethrow(Rethrow node) {
    endBasicBlock();
  }
  void visitThrow(Throw node) {
    endBasicBlock();
  }
  void visitUnreachable(Unreachable node) {
    endBasicBlock();
  }

  void visitLetMutable(LetMutable node) {
    escape(node.valueRef);
  }

  void visitLetCont(LetCont node) {
    if (unescaped.isNotEmpty) {
      // Ensure we do not lift a LetCont if there is a sink target set above
      // the current node.
      sinkLetConts();
      letConts.add(node);
    }
  }

  void sinkLetConts() {
    if (letContSinkTarget != null) {
      for (LetCont letCont in letConts.reversed) {
        letCont..remove()..insertBelow(letContSinkTarget);
      }
      letContSinkTarget = null;
    }
  }

  void endBasicBlock() {
    sinkLetConts();
    letConts.clear();
    unescaped.clear();
  }

  void visitLetPrim(LetPrim node) {
    Primitive prim = node.primitive;
    if (prim is CreateInstance) {
      unescaped.add(prim);
      prim.argumentRefs.forEach(escape);
      return;
    }
    if (unescaped.isEmpty) return;
    if (prim is SetField) {
      escape(prim.valueRef);
      Primitive object = prim.object;
      if (object is CreateInstance && unescaped.contains(object)) {
        int index = getFieldIndex(object.classElement, prim.field);
        if (index == -1) {
          // This field is not initialized at creation time, so we cannot pull
          // set SetField into the CreateInstance instruction.  We have to
          // leave the instruction here, and this counts as a use of the object.
          escape(prim.objectRef);
        } else {
          // Replace the field initializer with the new value. There are no uses
          // of the object before this, so the old value cannot have been seen.
          object.argumentRefs[index].changeTo(prim.value);
          prim.destroy();
          // The right-hand side might not be in scope at the CreateInstance.
          // Sink the creation down to this point.
          rebindCreateInstanceAt(object, node);
          letContSinkTarget = node;
        }
      }
      return;
    }
    if (prim is GetField) {
      // When reading the field of a newly created object, just use the initial
      // value and destroy the GetField. This can unblock the other optimization
      // since we remove a use of the object.
      Primitive object = prim.object;
      if (object is CreateInstance && unescaped.contains(object)) {
        int index = getFieldIndex(object.classElement, prim.field);
        if (index == -1) {
          escape(prim.objectRef);
        } else {
          prim.replaceUsesWith(object.argument(index));
          prim.destroy();
          node.remove();
        }
      }
      return;
    }
    escapeVisitor.visit(node.primitive);
  }

  void rebindCreateInstanceAt(CreateInstance prim, LetPrim newBinding) {
    removeBinding(prim);
    newBinding.primitive = prim;
    prim.parent = newBinding;
  }

  /// Returns the index of [field] in the canonical initialization order in
  /// [classElement], or -1 if the field is not initialized at creation time
  /// for that class.
  int getFieldIndex(ClassElement classElement, FieldElement field) {
    // There is no stored map from a field to its index in a given class, so we
    // have to iterate over all instance fields until we find it.
    int current = -1, index = -1;
    classElement.forEachInstanceField((host, currentField) {
      if (!backend.isNativeOrExtendsNative(host)) {
        ++current;
        if (currentField == field) {
          index = current;
        }
      }
    }, includeSuperAndInjectedMembers: true);
    return index;
  }

  void removeBinding(Primitive prim) {
    LetPrim node = prim.parent;
    node.remove();
  }
}

class EscapeVisitor extends DeepRecursiveVisitor {
  final UseFieldInitializers main;
  EscapeVisitor(this.main);

  processReference(Reference ref) {
    main.escape(ref);
  }
}
