// Copyright (c) 2017, 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.
//
// VMOptions=--optimization-counter-threshold=1000 --no-background-compilation

// Regression test for correct LICM and type propagation.

class Attribute {
  final id = 123;
}

abstract class Name {
  Name(this.name);
  final String name;
  get attr;

  @pragma('vm:prefer-inline')
  int compareTo(other) {
    int nameCompare = name.compareTo(other.name);
    if (nameCompare != 0) return nameCompare;
    if (attr == null) return 0;
    return attr.id - other.attr.id;
  }
}

class AName extends Name {
  AName() : super("abc");
  final attr = new Attribute();
}

class BName extends Name {
  BName(name) : super(name);
  get attr => null;
}

class Member {
  Member(this.name);
  var name;
}

Member? find(List<Member> members, Name name) {
  int low = 0, high = members.length - 1;
  while (low <= high) {
    int mid = low + ((high - low) >> 1);
    Member pivot = members[mid];
    int comparison = name.compareTo(pivot.name);
    if (comparison < 0) {
      high = mid - 1;
    } else if (comparison > 0) {
      low = mid + 1;
    } else {
      return pivot;
    }
  }
  return null;
}

main() {
  var list = [
    new Member(new AName()),
    new Member(new BName("a")),
    new Member(new BName("b")),
    new Member(new BName("c")),
    new Member(new BName("d")),
  ];

  find(list, new AName());
  find(list, new BName("e"));
  find(list, new BName("b"));
  for (var i = 0; i < 1000; ++i) {
    find(list, new BName("b"));
    find(list, new BName("e"));
  }
}
