Port inference tests, #5 of 5

Change-Id: I384056289dfa99991aa42fbe0baadedc6c208b6f
Reviewed-on: https://dart-review.googlesource.com/34586
Reviewed-by: Sigmund Cherem <sigmund@google.com>
diff --git a/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart b/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
index dfe9783..d43c8c0 100644
--- a/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
+++ b/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
@@ -542,6 +542,12 @@
   if (id is NodeId) {
     return new SourceSpan(mainUri, id.value, id.value + 1);
   } else if (id is ElementId) {
+    String memberName = id.memberName;
+    bool isSetter = false;
+    if (memberName != '[]=' && memberName.endsWith('=')) {
+      isSetter = true;
+      memberName = memberName.substring(0, memberName.length - 1);
+    }
     LibraryEntity library = elementEnvironment.lookupLibrary(mainUri);
     if (id.className != null) {
       ClassEntity cls =
@@ -549,23 +555,22 @@
       if (cls == null) {
         throw new ArgumentError("No class '${id.className}' in $mainUri.");
       }
-      MemberEntity member =
-          elementEnvironment.lookupClassMember(cls, id.memberName);
+      MemberEntity member = elementEnvironment
+          .lookupClassMember(cls, memberName, setter: isSetter);
       if (member == null) {
         ConstructorEntity constructor =
-            elementEnvironment.lookupConstructor(cls, id.memberName);
+            elementEnvironment.lookupConstructor(cls, memberName);
         if (constructor == null) {
-          throw new ArgumentError(
-              "No class member '${id.memberName}' in $cls.");
+          throw new ArgumentError("No class member '${memberName}' in $cls.");
         }
         return constructor;
       }
       return member;
     } else {
-      MemberEntity member =
-          elementEnvironment.lookupLibraryMember(library, id.memberName);
+      MemberEntity member = elementEnvironment
+          .lookupLibraryMember(library, memberName, setter: isSetter);
       if (member == null) {
-        throw new ArgumentError("No member '${id.memberName}' in $mainUri.");
+        throw new ArgumentError("No member '${memberName}' in $mainUri.");
       }
       return member;
     }
diff --git a/tests/compiler/dart2js/equivalence/show_helper.dart b/tests/compiler/dart2js/equivalence/show_helper.dart
index d37f502..bb72432 100644
--- a/tests/compiler/dart2js/equivalence/show_helper.dart
+++ b/tests/compiler/dart2js/equivalence/show_helper.dart
@@ -8,37 +8,40 @@
 import 'package:args/args.dart';
 import 'package:compiler/src/commandline_options.dart';
 import 'package:compiler/src/filenames.dart';
-import 'package:compiler/src/inferrer/inferrer_engine.dart';
 import 'package:compiler/src/io/source_file.dart';
 import 'package:compiler/src/source_file_provider.dart';
 import '../kernel/test_helpers.dart';
 import 'id_equivalence_helper.dart';
 
-show(List<String> args, ComputeMemberDataFunction computeAstData,
-    ComputeMemberDataFunction computeKernelData) async {
+ArgParser createArgParser() {
   ArgParser argParser = new ArgParser(allowTrailingOptions: true);
   argParser.addFlag('verbose', negatable: true, defaultsTo: false);
   argParser.addFlag('colors', negatable: true);
   argParser.addFlag('all', negatable: false, defaultsTo: false);
   argParser.addFlag('use-kernel', negatable: false, defaultsTo: false);
-  ArgResults argResults = argParser.parse(args);
+  return argParser;
+}
+
+show(ArgResults argResults, ComputeMemberDataFunction computeAstData,
+    ComputeMemberDataFunction computeKernelData) async {
   if (argResults.wasParsed('colors')) {
     useColors = argResults['colors'];
   }
   bool verbose = argResults['verbose'];
   bool useKernel = argResults['use-kernel'];
 
-  InferrerEngineImpl.useSorterForTesting = true;
   String file = argResults.rest.first;
   Uri entryPoint = Uri.base.resolve(nativeToUriPath(file));
   List<String> show;
-  if (argResults.rest.length > 1) {
+  if (argResults['all']) {
+    show = null;
+  } else if (argResults.rest.length > 1) {
     show = argResults.rest.skip(1).toList();
   } else {
     show = [entryPoint.pathSegments.last];
   }
 
-  List<String> options = <String>[];
+  List<String> options = <String>[stopAfterTypeInference];
   if (useKernel) {
     options.add(Flags.useKernel);
   }
diff --git a/tests/compiler/dart2js/inference/call_site_simple_type_inferer_test.dart b/tests/compiler/dart2js/inference/call_site_simple_type_inferer_test.dart
deleted file mode 100644
index 4047641..0000000
--- a/tests/compiler/dart2js/inference/call_site_simple_type_inferer_test.dart
+++ /dev/null
@@ -1,297 +0,0 @@
-// 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.
-
-/// TODO(johnniwinther): Port this test to use the equivalence framework.
-/// Currently it only works with the mock compiler.
-
-import 'package:async_helper/async_helper.dart';
-import 'package:compiler/src/elements/elements.dart';
-import 'package:compiler/src/types/masks.dart';
-import 'package:expect/expect.dart';
-
-import 'type_mask_test_helper.dart';
-import '../compiler_helper.dart';
-
-void compileAndFind(String code, String className, String memberName,
-    bool disableInlining, check(compiler, element)) {
-  Uri uri = new Uri(scheme: 'source');
-  var compiler = mockCompilerFor(code, uri, disableInlining: disableInlining);
-  asyncTest(() => compiler.run(uri).then((_) {
-        ClassElement cls = findElement(compiler, className);
-        var member = cls.lookupLocalMember(memberName);
-        return check(compiler, member);
-      }));
-}
-
-const String TEST_1 = r"""
-  class A {
-    x(p) => p;
-  }
-  main() { new A().x("s"); }
-""";
-
-const String TEST_2 = r"""
-  class A {
-    x(p) => p;
-  }
-  main() { new A().x(1); }
-""";
-
-const String TEST_3 = r"""
-  class A {
-    x(p) => x(p - 1);
-  }
-  main() { new A().x(1); }
-""";
-
-const String TEST_4 = r"""
-  class A {
-    x(p) => x(p - 1);
-  }
-  main() { new A().x(1.5); }
-""";
-
-const String TEST_5 = r"""
-  class A {
-    x(p) => p;
-  }
-  main() {
-    new A().x(1);
-    new A().x(1.5);
-  }
-""";
-
-const String TEST_6 = r"""
-  class A {
-    x(p) => p;
-  }
-  main() {
-    new A().x(1.5);
-    new A().x(1);
-  }
-""";
-
-const String TEST_7a = r"""
-  class A {
-    x(p) => x("x");
-  }
-  main() {
-    new A().x(1);
-  }
-""";
-
-const String TEST_7b = r"""
-  class A {
-    x(p) => x("x");
-  }
-  main() {
-    new A().x({});
-  }
-""";
-
-const String TEST_8 = r"""
-  class A {
-    x(p1, p2, p3) => x(p1, "x", {});
-  }
-  main() {
-    new A().x(1, 2, 3);
-  }
-""";
-
-const String TEST_9 = r"""
-  class A {
-    x(p1, p2) => x(p1, p2);
-  }
-  main() {
-    new A().x(1, 2);
-  }
-""";
-
-const String TEST_10 = r"""
-  class A {
-    x(p1, p2) => x(p1, p2);
-  }
-  void f(p) {
-    p.x("x", "y");
-  }
-  main() {
-    f(null);
-    new A().x(1, 2);
-  }
-""";
-
-const String TEST_11 = r"""
-  class A {
-    x(p1, p2) => x(1, 2);
-  }
-  main() {
-    new A().x("x", "y");
-  }
-""";
-
-const String TEST_12 = r"""
-  class A {
-    x(p1, [p2 = 1]) => 1;
-  }
-  main() {
-    new A().x("x", 1);
-    new A().x("x");
-  }
-""";
-
-const String TEST_13 = r"""
-  class A {
-    x(p) => 1;
-  }
-  f(p) => p.x(2.2);
-  main() {
-    new A().x(1);
-    f(new A());
-  }
-""";
-
-const String TEST_14 = r"""
-  class A {
-    x(p1, [p2 = "s"]) => 1;
-  }
-  main() {
-    new A().x(1);
-  }
-""";
-
-const String TEST_15 = r"""
-  class A {
-    x(p1, [p2 = true]) => 1;
-  }
-  f(p) => p.a("x");
-  main() {
-    new A().x("x");
-    new A().x("x", false);
-    f(null);
-  }
-""";
-
-const String TEST_16 = r"""
-  class A {
-    x(p1, [p2 = 1, p3 = "s"]) => 1;
-  }
-  main() {
-    new A().x(1);
-    new A().x(1, 2);
-    new A().x(1, 2, "x");
-    new A().x(1, p2: 2);
-    new A().x(1, p3: "x");
-    new A().x(1, p3: "x", p2: 2);
-    new A().x(1, p2: 2, p3: "x");
-  }
-""";
-
-const String TEST_17 = r"""
-  class A {
-    x(p1, [p2 = 1, p3 = "s"]) => 1;
-  }
-  main() {
-    new A().x(1, true, 1.1);
-    new A().x(1, false, 2.2);
-    new A().x(1, p3: 3.3, p2: true);
-    new A().x(1, p2: false, p3: 4.4);
-  }
-""";
-
-const String TEST_18 = r"""
-  class A {
-    x(p1, p2) => x(p1, p2);
-  }
-  class B extends A {
-  }
-  main() {
-    new B().x("a", "b");
-    new A().x(1, 2);
-  }
-""";
-
-typedef List<TypeMask> TestCallback(CommonMasks masks);
-
-void doTest(String test, bool enableInlining, TestCallback f) {
-  compileAndFind(test, 'A', 'x', enableInlining, (compiler, element) {
-    var inferrer = compiler.globalInference.typesInferrerInternal;
-    var closedWorld = inferrer.closedWorld;
-    var expectedTypes = f(closedWorld.commonMasks);
-    var signature = element.functionSignature;
-    int index = 0;
-    signature.forEachParameter((Element element) {
-      Expect.equals(expectedTypes[index++],
-          simplify(inferrer.getTypeOfParameter(element), closedWorld), test);
-    });
-    Expect.equals(index, expectedTypes.length);
-  });
-}
-
-void runTest(String test, TestCallback f) {
-  doTest(test, false, f);
-  doTest(test, true, f);
-}
-
-void test() {
-  runTest(TEST_1, (commonMasks) => [commonMasks.stringType]);
-  runTest(TEST_2, (commonMasks) => [commonMasks.uint31Type]);
-  runTest(TEST_3, (commonMasks) => [commonMasks.intType]);
-  runTest(TEST_4, (commonMasks) => [commonMasks.numType]);
-  runTest(TEST_5, (commonMasks) => [commonMasks.numType]);
-  runTest(TEST_6, (commonMasks) => [commonMasks.numType]);
-  runTest(TEST_7a, (commonMasks) => [commonMasks.interceptorType]);
-  runTest(TEST_7b, (commonMasks) => [commonMasks.dynamicType.nonNullable()]);
-
-  runTest(
-      TEST_8,
-      (commonMasks) => [
-            commonMasks.uint31Type,
-            commonMasks.interceptorType,
-            commonMasks.dynamicType.nonNullable()
-          ]);
-  runTest(TEST_9,
-      (commonMasks) => [commonMasks.uint31Type, commonMasks.uint31Type]);
-  runTest(TEST_10,
-      (commonMasks) => [commonMasks.uint31Type, commonMasks.uint31Type]);
-  runTest(
-      TEST_11,
-      (commonMasks) =>
-          [commonMasks.interceptorType, commonMasks.interceptorType]);
-
-  runTest(TEST_12,
-      (commonMasks) => [commonMasks.stringType, commonMasks.uint31Type]);
-
-  runTest(TEST_13, (commonMasks) => [commonMasks.numType]);
-
-  runTest(TEST_14,
-      (commonMasks) => [commonMasks.uint31Type, commonMasks.stringType]);
-
-  runTest(
-      TEST_15, (commonMasks) => [commonMasks.stringType, commonMasks.boolType]);
-
-  runTest(
-      TEST_16,
-      (commonMasks) => [
-            commonMasks.uint31Type,
-            commonMasks.uint31Type,
-            commonMasks.stringType
-          ]);
-
-  runTest(
-      TEST_17,
-      (commonMasks) => [
-            commonMasks.uint31Type,
-            commonMasks.boolType,
-            commonMasks.doubleType
-          ]);
-
-  runTest(
-      TEST_18,
-      (commonMasks) =>
-          [commonMasks.interceptorType, commonMasks.interceptorType]);
-}
-
-void main() {
-  test();
-}
diff --git a/tests/compiler/dart2js/inference/callers/field_access.dart b/tests/compiler/dart2js/inference/callers/field_access.dart
new file mode 100644
index 0000000..71699e9
--- /dev/null
+++ b/tests/compiler/dart2js/inference/callers/field_access.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2018, 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.
+
+/*element: B.:[main]*/
+class A {
+  /*element: A.field:[main]*/
+  var field;
+}
+
+/*element: A.:[main]*/
+class B {
+  /*element: B.field:[main]*/
+  var field;
+}
+
+main() {
+  new A().field;
+  new B().field;
+}
diff --git a/tests/compiler/dart2js/inference/callers_test.dart b/tests/compiler/dart2js/inference/callers_test.dart
new file mode 100644
index 0000000..b88f07f
--- /dev/null
+++ b/tests/compiler/dart2js/inference/callers_test.dart
@@ -0,0 +1,145 @@
+// Copyright (c) 2018, 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 'dart:io';
+import 'package:async_helper/async_helper.dart';
+import 'package:compiler/src/closure.dart';
+import 'package:compiler/src/common.dart';
+import 'package:compiler/src/compiler.dart';
+import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
+import 'package:compiler/src/elements/elements.dart';
+import 'package:compiler/src/elements/entities.dart';
+import 'package:compiler/src/inferrer/inferrer_engine.dart';
+import 'package:compiler/src/inferrer/type_graph_inferrer.dart';
+import 'package:compiler/src/kernel/element_map.dart';
+import 'package:compiler/src/kernel/kernel_backend_strategy.dart';
+import 'package:compiler/src/tree/nodes.dart' as ast;
+import 'package:kernel/ast.dart' as ir;
+import '../equivalence/id_equivalence.dart';
+import '../equivalence/id_equivalence_helper.dart';
+
+main(List<String> args) {
+  InferrerEngineImpl.retainDataForTesting = true;
+  asyncTest(() async {
+    Directory dataDir =
+        new Directory.fromUri(Platform.script.resolve('callers'));
+    await checkTests(dataDir, computeMemberAstCallers, computeMemberIrCallers,
+        args: args, options: [stopAfterTypeInference]);
+  });
+}
+
+/// Compute callers data for [_member] as a [MemberElement].
+///
+/// Fills [actualMap] with the data.
+void computeMemberAstCallers(
+    Compiler compiler, MemberEntity _member, Map<Id, ActualData> actualMap,
+    {bool verbose: false}) {
+  MemberElement member = _member;
+  ResolvedAst resolvedAst = member.resolvedAst;
+  compiler.reporter.withCurrentElement(member.implementation, () {
+    new CallersAstComputer(compiler.reporter, actualMap, resolvedAst,
+            compiler.globalInference.typesInferrerInternal)
+        .run();
+  });
+}
+
+abstract class ComputeValueMixin<T> {
+  TypeGraphInferrer get inferrer;
+
+  String getMemberValue(MemberEntity member) {
+    Iterable<MemberEntity> callers = inferrer.getCallersOfForTesting(member);
+    if (callers != null) {
+      List<String> names = callers.map((MemberEntity member) {
+        StringBuffer sb = new StringBuffer();
+        if (member.enclosingClass != null) {
+          sb.write(member.enclosingClass.name);
+          sb.write('.');
+        }
+        sb.write(member.name);
+        if (member.isSetter) {
+          sb.write('=');
+        }
+        return sb.toString();
+      }).toList()
+        ..sort();
+      return '[${names.join(',')}]';
+    }
+    return null;
+  }
+}
+
+/// AST visitor for computing side effects data for a member.
+class CallersAstComputer extends AstDataExtractor
+    with ComputeValueMixin<ast.Node> {
+  final TypeGraphInferrer inferrer;
+
+  CallersAstComputer(DiagnosticReporter reporter, Map<Id, ActualData> actualMap,
+      ResolvedAst resolvedAst, this.inferrer)
+      : super(reporter, actualMap, resolvedAst);
+
+  @override
+  String computeElementValue(Id id, AstElement element) {
+    if (element.isParameter) {
+      return null;
+    } else if (element.isLocal && element.isFunction) {
+      LocalFunctionElement localFunction = element;
+      return getMemberValue(localFunction.callMethod);
+    } else {
+      MemberElement member = element.declaration;
+      return getMemberValue(member);
+    }
+  }
+
+  @override
+  String computeNodeValue(Id id, ast.Node node, [AstElement element]) {
+    if (element != null && element.isLocal && element.isFunction) {
+      return computeElementValue(id, element);
+    }
+    return null;
+  }
+}
+
+/// Compute callers data for [member] from kernel based inference.
+///
+/// Fills [actualMap] with the data.
+void computeMemberIrCallers(
+    Compiler compiler, MemberEntity member, Map<Id, ActualData> actualMap,
+    {bool verbose: false}) {
+  KernelBackendStrategy backendStrategy = compiler.backendStrategy;
+  KernelToElementMapForBuilding elementMap = backendStrategy.elementMap;
+  MemberDefinition definition = elementMap.getMemberDefinition(member);
+  new CallersIrComputer(
+          compiler.reporter,
+          actualMap,
+          elementMap,
+          compiler.globalInference.typesInferrerInternal,
+          backendStrategy.closureDataLookup as ClosureDataLookup<ir.Node>)
+      .run(definition.node);
+}
+
+/// AST visitor for computing side effects data for a member.
+class CallersIrComputer extends IrDataExtractor
+    with ComputeValueMixin<ir.Node> {
+  final TypeGraphInferrer inferrer;
+  final KernelToElementMapForBuilding _elementMap;
+  final ClosureDataLookup<ir.Node> _closureDataLookup;
+
+  CallersIrComputer(DiagnosticReporter reporter, Map<Id, ActualData> actualMap,
+      this._elementMap, this.inferrer, this._closureDataLookup)
+      : super(reporter, actualMap);
+
+  @override
+  String computeMemberValue(Id id, ir.Member node) {
+    return getMemberValue(_elementMap.getMember(node));
+  }
+
+  @override
+  String computeNodeValue(Id id, ir.TreeNode node) {
+    if (node is ir.FunctionExpression || node is ir.FunctionDeclaration) {
+      ClosureRepresentationInfo info = _closureDataLookup.getClosureInfo(node);
+      return getMemberValue(info.callMethod);
+    }
+    return null;
+  }
+}
diff --git a/tests/compiler/dart2js/inference/concrete_type_inference_test.dart b/tests/compiler/dart2js/inference/concrete_type_inference_test.dart
deleted file mode 100644
index 4b1b6b5..0000000
--- a/tests/compiler/dart2js/inference/concrete_type_inference_test.dart
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright (c) 2012, 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.
-
-/// TODO(johnniwinther): Port this test to use the equivalence framework.
-
-import 'dart:async';
-import 'package:expect/expect.dart';
-import 'package:async_helper/async_helper.dart';
-import '../compiler_helper.dart';
-
-Future compileAndFind(String code, String name, check(compiler, element)) {
-  Uri uri = new Uri(scheme: 'source');
-  var compiler = mockCompilerFor(code, uri);
-  return compiler.run(uri).then((_) {
-    var element = findElement(compiler, name);
-    check(compiler, element);
-  });
-}
-
-void checkPrintType(String expression, checkType(closedWorld, type)) {
-  asyncTest(() => compileAndFind('main() { print($expression); }', 'print',
-          (compiler, printElement) {
-        var parameter = printElement.functionSignature.requiredParameters.first;
-        checkType(compiler.resolutionWorldBuilder.closedWorldForTesting,
-            _typeOf(compiler, parameter));
-      }));
-
-  asyncTest(() =>
-      compileAndFind('main() { var x = print; print($expression); }', 'print',
-          (compiler, printElement) {
-        var parameter = printElement.functionSignature.requiredParameters.first;
-        checkType(compiler.resolutionWorldBuilder.closedWorldForTesting,
-            _typeOf(compiler, parameter));
-      }));
-
-  asyncTest(() => compileAndFind(
-          'main() { print($expression); print($expression); }', 'print',
-          (compiler, printElement) {
-        var parameter = printElement.functionSignature.requiredParameters.first;
-        checkType(compiler.resolutionWorldBuilder.closedWorldForTesting,
-            _typeOf(compiler, parameter));
-      }));
-}
-
-void testBasicTypes() {
-  checkPrintType('true', (closedWorld, type) {
-    if (type.isForwarding) type = type.forwardTo;
-    Expect.identical(closedWorld.commonMasks.boolType, type);
-  });
-  checkPrintType('1.5', (closedWorld, type) {
-    Expect.identical(closedWorld.commonMasks.doubleType, type);
-  });
-  checkPrintType('1', (closedWorld, type) {
-    Expect.identical(closedWorld.commonMasks.uint31Type, type);
-  });
-  checkPrintType('[]', (closedWorld, type) {
-    if (type.isForwarding) type = type.forwardTo;
-    Expect.identical(closedWorld.commonMasks.growableListType, type);
-  });
-  checkPrintType('null', (closedWorld, type) {
-    Expect.identical(closedWorld.commonMasks.nullType, type);
-  });
-  checkPrintType('"foo"', (closedWorld, type) {
-    Expect.isTrue(
-        closedWorld.commonMasks.stringType.containsOnlyString(closedWorld));
-  });
-}
-
-void testOptionalParameters() {
-  compileAndFind('fisk(a, [b, c]) {} main() { fisk(1); }', 'fisk',
-      (compiler, fiskElement) {
-    var firstParameter = fiskElement.functionSignature.requiredParameters[0];
-    var secondParameter = fiskElement.functionSignature.optionalParameters[0];
-    var thirdParameter = fiskElement.functionSignature.optionalParameters[1];
-    var commonMasks =
-        compiler.resolutionWorldBuilder.closedWorldForTesting.commonMasks;
-    Expect.identical(commonMasks.uint31Type, _typeOf(compiler, firstParameter));
-    Expect.identical(commonMasks.nullType, _typeOf(compiler, secondParameter));
-    Expect.identical(commonMasks.nullType, _typeOf(compiler, thirdParameter));
-  });
-}
-
-void main() {
-  testBasicTypes();
-  testOptionalParameters();
-}
-
-_typeOf(compiler, parameter) =>
-    compiler.globalInference.results.resultOfParameter(parameter).type;
diff --git a/tests/compiler/dart2js/inference/data/call_site.dart b/tests/compiler/dart2js/inference/data/call_site.dart
new file mode 100644
index 0000000..e9bcd9f
--- /dev/null
+++ b/tests/compiler/dart2js/inference/data/call_site.dart
@@ -0,0 +1,309 @@
+// Copyright (c) 2018, 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.
+
+/*element: main:[null]*/
+main() {
+  test1();
+  test2();
+  test3();
+  test4();
+  test5();
+  test6();
+  test7();
+  test8();
+  test9();
+  test10();
+  test11();
+  test12();
+  test13();
+  test14();
+  test15();
+  test16();
+  test17();
+  test18();
+  test19();
+}
+
+/*element: A1.:[exact=A1]*/
+class A1 {
+  /*element: A1.x1:Value([exact=JSString], value: "s")*/
+  x1(
+          /*Value([exact=JSString], value: "s")*/ p) =>
+      p;
+}
+
+/*element: test1:[null]*/
+test1() {
+  new A1(). /*invoke: [exact=A1]*/ x1("s");
+}
+
+/*element: A2.:[exact=A2]*/
+class A2 {
+  /*element: A2.x2:[exact=JSUInt31]*/
+  x2(/*[exact=JSUInt31]*/ p) => p;
+}
+
+/*element: test2:[null]*/
+test2() {
+  new A2(). /*invoke: [exact=A2]*/ x2(1);
+}
+
+/*element: A3.:[exact=A3]*/
+class A3 {
+  /*element: A3.x3:[empty]*/
+  x3(/*[subclass=JSInt]*/ p) => /*invoke: [exact=A3]*/ x3(
+      p /*invoke: [subclass=JSInt]*/ - 1);
+}
+
+/*element: test3:[null]*/
+test3() {
+  new A3(). /*invoke: [exact=A3]*/ x3(1);
+}
+
+/*element: A4.:[exact=A4]*/
+class A4 {
+  /*element: A4.x4:[empty]*/
+  x4(/*[subclass=JSNumber]*/ p) => /*invoke: [exact=A4]*/ x4(
+      p /*invoke: [subclass=JSNumber]*/ - 1);
+}
+
+/*element: test4:[null]*/
+test4() {
+  new A4(). /*invoke: [exact=A4]*/ x4(1.5);
+}
+
+/*element: A5.:[exact=A5]*/
+class A5 {
+  /*element: A5.x5:Union([exact=JSDouble], [exact=JSUInt31])*/
+  x5(
+          /*Union([exact=JSDouble], [exact=JSUInt31])*/ p) =>
+      p;
+}
+
+/*element: test5:[null]*/
+test5() {
+  new A5(). /*invoke: [exact=A5]*/ x5(1);
+  new A5(). /*invoke: [exact=A5]*/ x5(1.5);
+}
+
+/*element: A6.:[exact=A6]*/
+class A6 {
+  /*element: A6.x6:Union([exact=JSDouble], [exact=JSUInt31])*/
+  x6(
+          /*Union([exact=JSDouble], [exact=JSUInt31])*/ p) =>
+      p;
+}
+
+/*element: test6:[null]*/
+test6() {
+  new A6(). /*invoke: [exact=A6]*/ x6(1.5);
+  new A6(). /*invoke: [exact=A6]*/ x6(1);
+}
+
+/*element: A7.:[exact=A7]*/
+class A7 {
+  /*element: A7.x7:[empty]*/
+  x7(
+      /*Union([exact=JSString], [exact=JSUInt31])*/ p) => /*invoke: [exact=A7]*/ x7("x");
+}
+
+/*element: test7:[null]*/
+test7() {
+  new A7(). /*invoke: [exact=A7]*/ x7(1);
+}
+
+/*element: A8.:[exact=A8]*/
+class A8 {
+  /*element: A8.x8:[empty]*/
+  x8(
+          /*Union([exact=JSString], [subclass=JsLinkedHashMap])*/ p) =>
+      /*invoke: [exact=A8]*/ x8("x");
+}
+
+/*element: test8:[null]*/
+test8() {
+  new A8(). /*invoke: [exact=A8]*/ x8({});
+}
+
+/*element: A9.:[exact=A9]*/
+class A9 {
+  /*element: A9.x9:[empty]*/ x9(
+          /*[exact=JSUInt31]*/ p1,
+          /*Union([exact=JSString], [exact=JSUInt31])*/ p2,
+          /*Union([exact=JSUInt31], [subclass=JsLinkedHashMap])*/ p3) =>
+      /*invoke: [exact=A9]*/ x9(p1, "x", {});
+}
+
+/*element: test9:[null]*/
+test9() {
+  new A9(). /*invoke: [exact=A9]*/ x9(1, 2, 3);
+}
+
+/*element: A10.:[exact=A10]*/
+class A10 {
+  /*element: A10.x10:[empty]*/ x10(
+      /*[exact=JSUInt31]*/ p1,
+      /*[exact=JSUInt31]*/ p2) => /*invoke: [exact=A10]*/ x10(p1, p2);
+}
+
+/*element: test10:[null]*/
+test10() {
+  new A10(). /*invoke: [exact=A10]*/ x10(1, 2);
+}
+
+/*element: A11.:[exact=A11]*/
+class A11 {
+  /*element: A11.x11:[empty]*/
+  x11(
+      /*[exact=JSUInt31]*/ p1,
+      /*[exact=JSUInt31]*/ p2) => /*invoke: [exact=A11]*/ x11(p1, p2);
+}
+
+/*element: f11:[null]*/
+void f11(/*[null]*/ p) {
+  p. /*invoke: [null]*/ x11("x", "y");
+}
+
+/*element: test11:[null]*/
+test11() {
+  f11(null);
+  new A11(). /*invoke: [exact=A11]*/ x11(1, 2);
+}
+
+/*element: A12.:[exact=A12]*/
+class A12 {
+  /*element: A12.x12:[empty]*/
+  x12(
+          /*Union([exact=JSString], [exact=JSUInt31])*/ p1,
+          /*Union([exact=JSString], [exact=JSUInt31])*/ p2) =>
+      /*invoke: [exact=A12]*/ x12(1, 2);
+}
+
+/*element: test12:[null]*/
+test12() {
+  new A12(). /*invoke: [exact=A12]*/ x12("x", "y");
+}
+
+/*element: A13.:[exact=A13]*/
+class A13 {
+  /*element: A13.x13:[exact=JSUInt31]*/
+  x13(
+          /*Value([exact=JSString], value: "x")*/ p1,
+          [/*[exact=JSUInt31]*/ p2 = 1]) =>
+      1;
+}
+
+/*element: test13:[null]*/
+test13() {
+  new A13(). /*invoke: [exact=A13]*/ x13("x", 1);
+  new A13(). /*invoke: [exact=A13]*/ x13("x");
+}
+
+/*element: A14.:[exact=A14]*/
+class A14 {
+  /*element: A14.x14:[exact=JSUInt31]*/
+  x14(
+          /*Union([exact=JSDouble], [exact=JSUInt31])*/ p) =>
+      1;
+}
+
+/*element: f14:[exact=JSUInt31]*/
+f14(/*[exact=A14]*/ p) => p. /*invoke: [exact=A14]*/ x14(2.2);
+
+/*element: test14:[null]*/
+test14() {
+  new A14(). /*invoke: [exact=A14]*/ x14(1);
+  f14(new A14());
+}
+
+/*element: A15.:[exact=A15]*/
+class A15 {
+  /*element: A15.x15:[exact=JSUInt31]*/
+  x15(/*[exact=JSUInt31]*/ p1,
+          [/*Value([exact=JSString], value: "s")*/ p2 = "s"]) =>
+      1;
+}
+
+/*element: test15:[null]*/
+test15() {
+  new A15(). /*invoke: [exact=A15]*/ x15(1);
+}
+
+/*element: A16.:[exact=A16]*/
+class A16 {
+  /*element: A16.x16:[exact=JSUInt31]*/
+  x16(
+          /*Value([exact=JSString], value: "x")*/ p1,
+          [/*[exact=JSBool]*/ p2 = true]) =>
+      1;
+}
+
+/*element: f16:[empty]*/
+f16(/*[null]*/ p) => p. /*invoke: [null]*/ a("x");
+
+/*element: test16:[null]*/
+test16() {
+  new A16(). /*invoke: [exact=A16]*/ x16("x");
+  new A16(). /*invoke: [exact=A16]*/ x16("x", false);
+  f16(null);
+}
+
+/*element: A17.:[exact=A17]*/
+class A17 {
+  /*element: A17.x17:[exact=JSUInt31]*/
+  x17(/*[exact=JSUInt31]*/ p1,
+          [/*[exact=JSUInt31]*/ p2 = 1, /*[exact=JSString]*/ p3 = "s"]) =>
+      1;
+}
+
+/*element: test17:[null]*/
+test17() {
+  new A17(). /*invoke: [exact=A17]*/ x17(1);
+  new A17(). /*invoke: [exact=A17]*/ x17(1, 2);
+  new A17(). /*invoke: [exact=A17]*/ x17(1, 2, "x");
+  // ignore: undefined_named_parameter
+  new A17(). /*invoke: [exact=A17]*/ x17(1, p2: 2);
+  // ignore: undefined_named_parameter
+  new A17(). /*invoke: [exact=A17]*/ x17(1, p3: "x");
+  // ignore: undefined_named_parameter
+  new A17(). /*invoke: [exact=A17]*/ x17(1, p3: "x", p2: 2);
+  // ignore: undefined_named_parameter
+  new A17(). /*invoke: [exact=A17]*/ x17(1, p2: 2, p3: "x");
+}
+
+/*element: A18.:[exact=A18]*/
+class A18 {
+  /*element: A18.x18:[exact=JSUInt31]*/
+  x18(/*[exact=JSUInt31]*/ p1,
+          [/*[exact=JSBool]*/ p2 = 1, /*[exact=JSDouble]*/ p3 = "s"]) =>
+      1;
+}
+
+/*element: test18:[null]*/
+test18() {
+  new A18(). /*invoke: [exact=A18]*/ x18(1, true, 1.1);
+  new A18(). /*invoke: [exact=A18]*/ x18(1, false, 2.2);
+  // ignore: undefined_named_parameter
+  new A18(). /*invoke: [exact=A18]*/ x18(1, p3: 3.3, p2: true);
+  // ignore: undefined_named_parameter
+  new A18(). /*invoke: [exact=A18]*/ x18(1, p2: false, p3: 4.4);
+}
+
+/*element: A19.:[exact=A19]*/
+class A19 {
+  /*element: A19.x19:[empty]*/
+  x19(
+          /*Union([exact=JSString], [exact=JSUInt31])*/ p1,
+          /*Union([exact=JSString], [exact=JSUInt31])*/ p2) =>
+      /*invoke: [subclass=A19]*/ x19(p1, p2);
+}
+
+/*element: B19.:[exact=B19]*/
+class B19 extends A19 {}
+
+/*element: test19:[null]*/
+test19() {
+  new B19(). /*invoke: [exact=B19]*/ x19("a", "b");
+  new A19(). /*invoke: [exact=A19]*/ x19(1, 2);
+}
diff --git a/tests/compiler/dart2js/inference/data/dictionary_types.dart b/tests/compiler/dart2js/inference/data/dictionary_types.dart
new file mode 100644
index 0000000..f6f3cc4
--- /dev/null
+++ b/tests/compiler/dart2js/inference/data/dictionary_types.dart
@@ -0,0 +1,196 @@
+// Copyright (c) 2018, 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.
+
+/*element: main:[null]*/
+main() {
+  test1();
+  test2();
+  test3();
+  test4();
+  test5();
+}
+
+/*element: dictionaryA1:Map([subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
+var dictionaryA1 = {'string': "aString", 'int': 42, 'double': 21.5, 'list': []};
+
+/*element: dictionaryB1:Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSDouble], list: Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null), stringTwo: Value([null|exact=JSString], value: "anotherString"), intTwo: [null|exact=JSUInt31]})*/
+var dictionaryB1 = {'string': "aString", 'int': 42, 'double': 21.5, 'list': []};
+
+/*element: otherDict1:Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSUInt31], [null|exact=JSString]), map: {stringTwo: Value([exact=JSString], value: "anotherString"), intTwo: [exact=JSUInt31]})*/
+var otherDict1 = {'stringTwo': "anotherString", 'intTwo': 84};
+
+/*element: int1:[exact=JSUInt31]*/
+var int1 = 0;
+
+/*element: anotherInt1:[exact=JSUInt31]*/
+var anotherInt1 = 0;
+
+/*element: nullOrInt1:[null|exact=JSUInt31]*/
+var nullOrInt1 = 0;
+
+/*element: dynamic1:[null|subclass=Object]*/
+var dynamic1 = 0;
+
+/*element: test1:[null]*/
+test1() {
+  dictionaryA1
+      . /*invoke: Map([subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
+      addAll(otherDict1);
+  dictionaryB1
+      . /*invoke: Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSDouble], list: Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null), stringTwo: Value([null|exact=JSString], value: "anotherString"), intTwo: [null|exact=JSUInt31]})*/
+      addAll({'stringTwo': "anotherString", 'intTwo': 84});
+  int1 = dictionaryB1
+      /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSDouble], list: Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null), stringTwo: Value([null|exact=JSString], value: "anotherString"), intTwo: [null|exact=JSUInt31]})*/
+      ['int'];
+  anotherInt1 = otherDict1
+      /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSUInt31], [null|exact=JSString]), map: {stringTwo: Value([exact=JSString], value: "anotherString"), intTwo: [exact=JSUInt31]})*/
+      ['intTwo'];
+  dynamic1 = dictionaryA1
+      /*Map([subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/ [
+      'int'];
+  nullOrInt1 = dictionaryB1
+      /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSDouble], list: Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null), stringTwo: Value([null|exact=JSString], value: "anotherString"), intTwo: [null|exact=JSUInt31]})*/
+      ['intTwo'];
+}
+
+/*element: dictionaryA2:Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSDouble], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+var dictionaryA2 = {'string': "aString", 'int': 42, 'double': 21.5, 'list': []};
+
+/*element: dictionaryB2:Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {string: Value([exact=JSString], value: "aString"), intTwo: [exact=JSUInt31], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+var dictionaryB2 = {'string': "aString", 'intTwo': 42, 'list': []};
+
+/*element: nullOrInt2:[null|exact=JSUInt31]*/
+var nullOrInt2 = 0;
+
+/*element: aString2:[exact=JSString]*/
+var aString2 = "";
+
+/*element: doubleOrNull2:[null|exact=JSDouble]*/
+var doubleOrNull2 = 22.2;
+
+/*element: test2:[null]*/
+test2() {
+  var union = dictionaryA2
+          /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSDouble], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+          ['foo']
+      ? dictionaryA2
+      : dictionaryB2;
+  nullOrInt2 = union
+      /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {int: [null|exact=JSUInt31], double: [null|exact=JSDouble], string: Value([exact=JSString], value: "aString"), intTwo: [null|exact=JSUInt31], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+      ['intTwo'];
+  aString2 = union
+      /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {int: [null|exact=JSUInt31], double: [null|exact=JSDouble], string: Value([exact=JSString], value: "aString"), intTwo: [null|exact=JSUInt31], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+      ['string'];
+  doubleOrNull2 = union
+      /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {int: [null|exact=JSUInt31], double: [null|exact=JSDouble], string: Value([exact=JSString], value: "aString"), intTwo: [null|exact=JSUInt31], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+      ['double'];
+}
+
+/*element: dictionary3:Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSDouble], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+var dictionary3 = {'string': "aString", 'int': 42, 'double': 21.5, 'list': []};
+/*element: keyD3:Value([exact=JSString], value: "double")*/
+var keyD3 = 'double';
+
+/*element: keyI3:Value([exact=JSString], value: "int")*/
+var keyI3 = 'int';
+
+/*element: keyN3:Value([exact=JSString], value: "notFoundInMap")*/
+var keyN3 = 'notFoundInMap';
+
+/*element: knownDouble3:[exact=JSDouble]*/
+var knownDouble3 = 42.2;
+
+/*element: intOrNull3:[null|exact=JSUInt31]*/
+var intOrNull3 = dictionary3
+    /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSDouble], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+    [keyI3];
+
+/*element: justNull3:[null]*/
+var justNull3 = dictionary3
+    /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSDouble], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+    [keyN3];
+
+/*element: test3:[null]*/
+test3() {
+  knownDouble3 = dictionary3
+      /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSDouble], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+      [keyD3];
+  // ignore: unused_local_variable
+  var x = [intOrNull3, justNull3];
+}
+
+class A4 {
+/*element: A4.:[exact=A4]*/
+  A4();
+/*element: A4.foo4:[exact=JSUInt31]*/
+  foo4(
+      /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSUInt31], [null|exact=JSString]), map: {anInt: [exact=JSUInt31], aString: Value([exact=JSString], value: "theString")})*/ value) {
+    return value /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSUInt31], [null|exact=JSString]), map: {anInt: [exact=JSUInt31], aString: Value([exact=JSString], value: "theString")})*/ [
+        'anInt'];
+  }
+}
+
+class B4 {
+/*element: B4.:[exact=B4]*/
+  B4();
+
+/*element: B4.foo4:[exact=JSUInt31]*/
+  foo4(
+      /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSUInt31], [null|exact=JSString]), map: {anInt: [exact=JSUInt31], aString: Value([exact=JSString], value: "theString")})*/ value) {
+    return 0;
+  }
+}
+
+/*element: test4:[null]*/
+test4() {
+  var dictionary = {'anInt': 42, 'aString': "theString"};
+  var it;
+  if ([true, false]
+      /*Container([exact=JSExtendableArray], element: [exact=JSBool], length: 2)*/
+      [0]) {
+    it = new A4();
+  } else {
+    it = new B4();
+  }
+  print(it. /*invoke: Union([exact=A4], [exact=B4])*/ foo4(
+          dictionary) /*invoke: [exact=JSUInt31]*/ +
+      2);
+}
+
+/*element: dict5:Map([null|subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
+var dict5 = makeMap5([1, 2]);
+
+/*element: notInt5:[null|subclass=Object]*/
+var notInt5 = 0;
+
+/*element: alsoNotInt5:[null|subclass=Object]*/
+var alsoNotInt5 = 0;
+
+/*element: makeMap5:Map([subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
+makeMap5(
+    /*Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 2)*/ values) {
+  return {
+    'moo': values
+        /*Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 2)*/
+        [0],
+    'boo': values
+        /*Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 2)*/
+        [1]
+  };
+}
+
+/*element: test5:[null]*/
+test5() {
+  dict5
+      /*update: Map([null|subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
+      ['goo'] = 42;
+  var closure =
+      /*Map([null|subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
+      () => dict5;
+  notInt5 = closure()['boo'];
+  alsoNotInt5 = dict5
+      /*Map([null|subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
+      ['goo'];
+  print("$notInt5 and $alsoNotInt5.");
+}
diff --git a/tests/compiler/dart2js/inference/data/map_tracer_keys.dart b/tests/compiler/dart2js/inference/data/map_tracer_keys.dart
new file mode 100644
index 0000000..fb02458
--- /dev/null
+++ b/tests/compiler/dart2js/inference/data/map_tracer_keys.dart
@@ -0,0 +1,189 @@
+// Copyright (c) 2018, 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.
+
+/*element: main:[null]*/
+main() {
+  test1();
+  test2();
+  test3();
+  test4();
+  test5();
+  test6();
+}
+
+/*element: aDouble1:[null|exact=JSDouble]*/
+double aDouble1 = 42.5;
+
+/*element: aList1:Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)*/
+List aList1 = [42];
+
+/*element: consume1:Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)*/
+consume1(
+        /*Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)*/ x) =>
+    x;
+
+/*element: test1:[null]*/
+test1() {
+  var theMap = {'a': 2.2, 'b': 3.3, 'c': 4.4};
+  theMap
+      /*update: Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSDouble], map: {a: [exact=JSDouble], b: [exact=JSDouble], c: [exact=JSDouble], d: [null|exact=JSDouble]})*/
+      ['d'] = 5.5;
+  /*iterator: [exact=LinkedHashMapKeyIterable]*/
+  /*current: [exact=LinkedHashMapKeyIterator]*/
+  /*moveNext: [exact=LinkedHashMapKeyIterator]*/
+  for (var key in theMap.
+      /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSDouble], map: {a: [exact=JSDouble], b: [exact=JSDouble], c: [exact=JSDouble], d: [null|exact=JSDouble]})*/
+      keys) {
+    aDouble1 = theMap
+        /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSDouble], map: {a: [exact=JSDouble], b: [exact=JSDouble], c: [exact=JSDouble], d: [null|exact=JSDouble]})*/
+        [key];
+  }
+  // We have to reference it somewhere, so that it always gets resolved.
+  consume1(aList1);
+}
+
+/*element: aDouble2:[null|exact=JSDouble]*/
+double aDouble2 = 42.5;
+
+/*element: aList2:Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null)*/
+List aList2 = [42];
+
+/*element: consume2:Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null)*/
+consume2(
+        /*Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null)*/ x) =>
+    x;
+
+/*element: test2:[null]*/
+test2() {
+  dynamic theMap = {'a': 2.2, 'b': 3.3, 'c': 4.4};
+  theMap
+      /*update: Map([subclass=JsLinkedHashMap], key: Union([exact=JSExtendableArray], [exact=JSString]), value: [null|exact=JSDouble])*/
+      [aList2] = 5.5;
+  /*iterator: [exact=LinkedHashMapKeyIterable]*/
+  /*current: [exact=LinkedHashMapKeyIterator]*/
+  /*moveNext: [exact=LinkedHashMapKeyIterator]*/
+  for (var key in theMap.
+      /*Map([subclass=JsLinkedHashMap], key: Union([exact=JSExtendableArray], [exact=JSString]), value: [null|exact=JSDouble])*/
+      keys) {
+    aDouble2 = theMap
+        /*Map([subclass=JsLinkedHashMap], key: Union([exact=JSExtendableArray], [exact=JSString]), value: [null|exact=JSDouble])*/
+        [key];
+  }
+  // We have to reference it somewhere, so that it always gets resolved.
+  consume2(aList2);
+}
+
+/*element: aDouble3:Union([exact=JSDouble], [null|exact=JSExtendableArray])*/
+double aDouble3 = 42.5;
+
+/*element: aList3:Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null)*/
+List aList3 = [42];
+
+/*element: consume3:Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null)*/
+consume3(
+        /*Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null)*/ x) =>
+    x;
+
+/*element: test3:[null]*/
+test3() {
+  dynamic theMap = {'a': 2.2, 'b': 3.3, 'c': 4.4};
+  theMap
+      /*update: Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [null|exact=JSExtendableArray]), map: {a: [exact=JSDouble], b: [exact=JSDouble], c: [exact=JSDouble], d: Container([null|exact=JSExtendableArray], element: [null|subclass=Object], length: null)})*/
+      ['d'] = aList3;
+  /*iterator: [exact=LinkedHashMapKeyIterable]*/
+  /*current: [exact=LinkedHashMapKeyIterator]*/
+  /*moveNext: [exact=LinkedHashMapKeyIterator]*/
+  for (var key in theMap.
+      /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [null|exact=JSExtendableArray]), map: {a: [exact=JSDouble], b: [exact=JSDouble], c: [exact=JSDouble], d: Container([null|exact=JSExtendableArray], element: [null|subclass=Object], length: null)})*/
+      keys) {
+    aDouble3 = theMap
+        /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [null|exact=JSExtendableArray]), map: {a: [exact=JSDouble], b: [exact=JSDouble], c: [exact=JSDouble], d: Container([null|exact=JSExtendableArray], element: [null|subclass=Object], length: null)})*/
+        [key];
+  }
+  // We have to reference it somewhere, so that it always gets resolved.
+  consume3(aList3);
+}
+
+/*element: aDouble4:[null|exact=JSDouble]*/
+double aDouble4 = 42.5;
+
+/*element: aList4:Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)*/
+List aList4 = [42];
+
+/*element: consume4:Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)*/
+consume4(
+        /*Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)*/ x) =>
+    x;
+
+/*element: test4:[null]*/
+test4() {
+  var theMap = {'a': 2.2, 'b': 3.3, 'c': 4.4, 'd': 5.5};
+  /*iterator: [exact=LinkedHashMapKeyIterable]*/
+  /*current: [exact=LinkedHashMapKeyIterator]*/
+  /*moveNext: [exact=LinkedHashMapKeyIterator]*/
+  for (var key in theMap.
+      /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSDouble], map: {a: [exact=JSDouble], b: [exact=JSDouble], c: [exact=JSDouble], d: [exact=JSDouble]})*/
+      keys) {
+    aDouble4 = theMap
+        /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSDouble], map: {a: [exact=JSDouble], b: [exact=JSDouble], c: [exact=JSDouble], d: [exact=JSDouble]})*/
+        [key];
+  }
+  // We have to reference it somewhere, so that it always gets resolved.
+  consume4(aList4);
+}
+
+/*element: aDouble5:[null|exact=JSDouble]*/
+double aDouble5 = 42.5;
+
+/*element: aList5:Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null)*/
+List aList5 = [42];
+
+/*element: consume5:Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null)*/
+consume5(
+        /*Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null)*/ x) =>
+    x;
+
+/*element: test5:[null]*/
+test5() {
+  var theMap = {'a': 2.2, 'b': 3.3, 'c': 4.4, aList5: 5.5};
+  /*iterator: [exact=LinkedHashMapKeyIterable]*/
+  /*current: [exact=LinkedHashMapKeyIterator]*/
+  /*moveNext: [exact=LinkedHashMapKeyIterator]*/
+  for (var key in theMap.
+      /*Map([subclass=JsLinkedHashMap], key: Union([exact=JSExtendableArray], [exact=JSString]), value: [null|exact=JSDouble])*/
+      keys) {
+    aDouble5 = theMap
+        /*Map([subclass=JsLinkedHashMap], key: Union([exact=JSExtendableArray], [exact=JSString]), value: [null|exact=JSDouble])*/
+        [key];
+  }
+  // We have to reference it somewhere, so that it always gets resolved.
+  consume5(aList5);
+}
+
+/*element: aDouble6:Union([null|exact=JSDouble], [null|exact=JSExtendableArray])*/
+double aDouble6 = 42.5;
+/*element: aList6:Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)*/
+List aList6 = [42];
+
+/*element: consume6:Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)*/
+consume6(
+        /*Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)*/ x) =>
+    x;
+
+/*element: test6:[null]*/
+test6() {
+  var theMap = {'a': 2.2, 'b': 3.3, 'c': 4.4, 'd': aList6};
+  /*iterator: [exact=LinkedHashMapKeyIterable]*/
+  /*current: [exact=LinkedHashMapKeyIterator]*/
+  /*moveNext: [exact=LinkedHashMapKeyIterator]*/
+  for (var key in theMap.
+      /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [null|exact=JSExtendableArray]), map: {a: [exact=JSDouble], b: [exact=JSDouble], c: [exact=JSDouble], d: Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)})*/
+      keys) {
+    aDouble6 = theMap
+        /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([null|exact=JSDouble], [null|exact=JSExtendableArray]), map: {a: [exact=JSDouble], b: [exact=JSDouble], c: [exact=JSDouble], d: Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)})*/
+        [key];
+  }
+  // We have to reference it somewhere, so that it always gets resolved.
+  consume6(aList6);
+}
diff --git a/tests/compiler/dart2js/inference/dictionary_types_test.dart b/tests/compiler/dart2js/inference/dictionary_types_test.dart
deleted file mode 100644
index 1d934e6..0000000
--- a/tests/compiler/dart2js/inference/dictionary_types_test.dart
+++ /dev/null
@@ -1,173 +0,0 @@
-// Copyright (c) 2014, 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.
-
-/// TODO(johnniwinther): Port this test to use the equivalence framework.
-
-import 'package:async_helper/async_helper.dart';
-import 'package:compiler/src/commandline_options.dart';
-import 'package:expect/expect.dart';
-
-import '../memory_compiler.dart';
-
-var SOURCES = const {
-  'AddAll.dart': """
-  var dictionaryA = {'string': "aString", 'int': 42, 'double': 21.5,
-                     'list': []};
-  var dictionaryB = {'string': "aString", 'int': 42, 'double': 21.5,
-                     'list': []};
-  var otherDict = {'stringTwo' : "anotherString", 'intTwo' : 84};
-  var int = 0;
-  var anotherInt = 0;
-  var nullOrInt = 0;
-  var dynamic = 0;
-
-  main() {
-    dictionaryA.addAll(otherDict);
-    dictionaryB.addAll({'stringTwo' : "anotherString", 'intTwo' : 84});
-    int = dictionaryB['int'];
-    anotherInt = otherDict['intTwo'];
-    dynamic = dictionaryA['int'];
-    nullOrInt = dictionaryB['intTwo'];
-  }
-""",
-  'Union.dart': """
-  var dictionaryA = {'string': "aString", 'int': 42, 'double': 21.5,
-                     'list': []};
-  var dictionaryB = {'string': "aString", 'intTwo': 42, 'list': []};
-  var nullOrInt = 0;
-  var aString = "";
-  var doubleOrNull = 22.2;
-  var key = "string";
-
-  main() {
-    var union = dictionaryA['foo'] ? dictionaryA : dictionaryB;
-    nullOrInt = union['intTwo'];
-    aString = union['string'];
-    doubleOrNull = union['double'];
-  }
-""",
-  'ValueType.dart': """
-  var dictionary = {'string': "aString", 'int': 42, 'double': 21.5, 'list': []};
-  var keyD = 'double';
-  var keyI = 'int';
-  var keyN = 'notFoundInMap';
-  var knownDouble = 42.2;
-  var intOrNull = dictionary[keyI];
-  var justNull = dictionary[keyN];
-
-  main() {
-    knownDouble = dictionary[keyD];
-    var x = [intOrNull, justNull];
-  }
-""",
-  'Propagation.dart': """
-  class A {
-    A();
-    foo(value) {
-      return value['anInt'];
-    }
-  }
-
-  class B {
-    B();
-    foo(value) {
-      return 0;
-    }
-  }
-
-  main() {
-    var dictionary = {'anInt': 42, 'aString': "theString"};
-    var it;
-    if ([true, false][0]) {
-      it = new A();
-    } else {
-      it = new B();
-    }
-    print(it.foo(dictionary) + 2);
-  }
-""",
-  'Bailout.dart': """
-  var dict = makeMap([1,2]);
-  var notInt = 0;
-  var alsoNotInt = 0;
-
-  makeMap(values) {
-    return {'moo': values[0], 'boo': values[1]};
-  }
-
-  main () {
-    dict['goo'] = 42;
-    var closure = () => dict;
-    notInt = closure()['boo'];
-    alsoNotInt = dict['goo'];
-    print("\$notInt and \$alsoNotInt.");
-  }
-"""
-};
-
-void main() {
-  asyncTest(() async {
-    print('--test from ast---------------------------------------------------');
-    await runTests(useKernel: false);
-    print('--test from kernel------------------------------------------------');
-    await runTests(useKernel: true);
-  });
-}
-
-runTests({bool useKernel}) async {
-  await compileAndTest("AddAll.dart", (types, getType, closedWorld) {
-    Expect.equals(getType('int'), types.uint31Type);
-    Expect.equals(getType('anotherInt'), types.uint31Type);
-    Expect.equals(getType('dynamic'), types.dynamicType);
-    Expect.equals(getType('nullOrInt'), types.uint31Type.nullable());
-  }, useKernel: useKernel);
-  await compileAndTest("Union.dart", (types, getType, closedWorld) {
-    Expect.equals(getType('nullOrInt'), types.uint31Type.nullable());
-    Expect.isTrue(getType('aString').containsOnlyString(closedWorld));
-    Expect.equals(getType('doubleOrNull'), types.doubleType.nullable());
-  }, useKernel: useKernel);
-  await compileAndTest("ValueType.dart", (types, getType, closedWorld) {
-    Expect.equals(getType('knownDouble'), types.doubleType);
-    Expect.equals(getType('intOrNull'), types.uint31Type.nullable());
-    Expect.equals(getType('justNull'), types.nullType);
-  }, useKernel: useKernel);
-  await compileAndTest("Propagation.dart", (code) {
-    Expect.isFalse(code.contains("J.\$add\$ns"));
-  }, createCode: true, useKernel: useKernel);
-  await compileAndTest("Bailout.dart", (types, getType, closedWorld) {
-    Expect.equals(getType('notInt'), types.dynamicType);
-    Expect.equals(getType('alsoNotInt'), types.dynamicType);
-    Expect.isFalse(getType('dict').isDictionary);
-  }, useKernel: useKernel);
-}
-
-compileAndTest(source, checker,
-    {bool createCode: false, bool useKernel}) async {
-  CompilationResult result = await runCompiler(
-      entryPoint: Uri.parse('memory:' + source),
-      memorySourceFiles: SOURCES,
-      beforeRun: (compiler) {
-        compiler.stopAfterTypeInference = !createCode;
-      },
-      options: useKernel ? [Flags.useKernel] : []);
-  var compiler = result.compiler;
-  var typesInferrer = compiler.globalInference.typesInferrerInternal;
-  var closedWorld = typesInferrer.closedWorld;
-  var elementEnvironment = closedWorld.elementEnvironment;
-  var commonMasks = closedWorld.commonMasks;
-  getType(String name) {
-    var element = elementEnvironment.lookupLibraryMember(
-        elementEnvironment.mainLibrary, name);
-    Expect.isNotNull(element, "No class '$name' found.");
-    return typesInferrer.getTypeOfMember(element);
-  }
-
-  if (!createCode) {
-    checker(commonMasks, getType, closedWorld);
-  } else {
-    var element = elementEnvironment.mainFunction;
-    var code = compiler.backend.getGeneratedCode(element);
-    checker(code);
-  }
-}
diff --git a/tests/compiler/dart2js/inference/field_type_simple_inferer_test.dart b/tests/compiler/dart2js/inference/field_type_simple_inferer_test.dart
deleted file mode 100644
index 6b46ce7..0000000
--- a/tests/compiler/dart2js/inference/field_type_simple_inferer_test.dart
+++ /dev/null
@@ -1,689 +0,0 @@
-// 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.
-
-/// TODO(johnniwinther): Port this test to use the equivalence framework.
-/// Currently it only works with the mock compiler.
-
-import 'package:expect/expect.dart';
-import 'package:async_helper/async_helper.dart';
-import 'package:compiler/src/types/types.dart' show TypeMask;
-import 'package:compiler/src/world.dart' show ClosedWorld;
-
-import 'type_mask_test_helper.dart';
-import '../compiler_helper.dart';
-
-void compileAndFind(String code, String className, String memberName,
-    bool disableInlining, check(compiler, element)) {
-  Uri uri = new Uri(scheme: 'source');
-  var compiler = mockCompilerFor(code, uri, disableInlining: disableInlining);
-  asyncTest(() => compiler.run(uri).then((_) {
-        dynamic cls = findElement(compiler, className);
-        var member = cls.lookupMember(memberName);
-        check(compiler, member);
-      }));
-}
-
-const String TEST_1 = r"""
-  class A {
-    int f;
-  }
-  main() { new A(); }
-""";
-
-const String TEST_2 = r"""
-  class A {
-    int f1;
-    int f2 = 1;
-  }
-  main() { new A(); }
-""";
-
-const String TEST_3 = r"""
-  class A {
-    int f1;
-    int f2;
-    A() : f1 = 1;
-  }
-  main() { new A().f2 = 2; }
-""";
-
-const String TEST_4 = r"""
-  class A {
-    int f1;
-    int f2;
-    A() : f1 = 1;
-  }
-  main() {
-    A a = new A();
-    a.f1 = "a";
-    a.f2 = "a";
-  }
-""";
-
-const String TEST_5 = r"""
-  class A {
-    int f1 = 1;
-    int f2 = 1;
-    A(x) {
-      f1 = "1";
-      if (x) {
-        f2 = "1";
-      } else {
-        f2 = "2";
-      }
-    }
-  }
-  main() {
-    new A(true);
-    new A(false);
-  }
-""";
-
-const String TEST_6 = r"""
-  class A {
-    int f1 = 1;
-    int f2 = 1;
-    A(x) {
-      f1 = "1";
-      if (x) {
-        f2 = "1";
-      } else {
-        f2 = "2";
-      }
-      if (x) {
-        f2 = new List();
-      } else {
-        f2 = new List();
-      }
-    }
-  }
-  main() {
-    new A(true);
-    new A(false);
-  }
-""";
-
-const String TEST_7 = r"""
-  class A {
-    int f1 = 1;
-    int f2 = 1;
-    A(x) {
-      f1 = "1";
-      if (x) {
-        f2 = "1";
-      } else {
-        f2 = "2";
-      }
-      if (x) {
-        f1 = new List();
-        f2 = new List();
-      } else {
-        f2 = new List();
-      }
-    }
-  }
-  main() {
-    new A(true);
-    new A(false);
-  }
-""";
-
-const String TEST_8 = r"""
-  class A {
-    int f;
-    A(x) {
-      if (x) {
-        f = "1";
-      } else {
-      }
-    }
-  }
-  main() {
-    new A(true);
-    new A(false);
-  }
-""";
-
-const String TEST_9 = r"""
-  class A {
-    int f;
-    A(x) {
-      if (x) {
-      } else {
-        f = "1";
-      }
-    }
-  }
-  main() {
-    new A(true);
-    new A(false);
-  }
-""";
-
-const String TEST_10 = r"""
-  class A {
-    int f;
-    A() {
-      f = 1;
-    }
-    m() => f + 1;
-  }
-  void f(x) { x.f = "2"; }
-  main() {
-    A a;
-    f(a);
-    a = new A();
-    a.m();
-  }
-""";
-
-const String TEST_11 = r"""
-  class S {
-    int fs = 1;
-    ms() { fs = 1; }
-  }
-
-  class A extends S {
-    m() { ms(); }
-  }
-
-  main() {
-    A a = new A();
-    a.m();
-  }
-""";
-
-const String TEST_12 = r"""
-  class S {
-    int fs = 1;
-    S() { fs = "2"; }
-  }
-
-  class A extends S {
-  }
-
-  main() {
-    A a = new A();
-  }
-""";
-
-const String TEST_13 = r"""
-  class S {
-    int fs;
-    S() { fs = 1; }
-  }
-
-  class A extends S {
-    A() { fs = 1; }
-  }
-
-  main() {
-    A a = new A();
-  }
-""";
-
-const String TEST_14 = r"""
-  class A {
-    var f;
-    A() { f = 1; }
-    A.other() { f = 2; }
-  }
-
-  main() {
-    A a = new A();
-    a = new A.other();
-  }
-""";
-
-const String TEST_15 = r"""
-  class A {
-    var f;
-    A() { f = "1"; }
-    A.other() { f = new List(); }
-  }
-
-  main() {
-    A a = new A();
-    a = new A.other();
-  }
-""";
-
-const String TEST_16 = r"""
-  class A {
-    var f;
-    A() { f = "1"; }
-    A.other() : f = 1 { }
-  }
-
-  main() {
-    A a = new A();
-    a = new A.other();
-  }
-""";
-
-const String TEST_17 = r"""
-  g([p]) => p.f = 1;
-  class A {
-    var f;
-    A(x) {
-      var a;
-      if (x) {
-        a = this;
-      } else {
-        a = g;
-      }
-      a(this);
-    }
-  }
-  main() {
-    new A(true);
-    new A(false);
-  }
-""";
-
-const String TEST_18 = r"""
-  class A {
-    var f1;
-    var f2;
-    var f3;
-    A(x) {
-      f1 = 1;
-      var a;
-      if (x) {
-        f2 = "1";
-        a = this;
-      } else {
-        a = 1;
-        f2 = "1";
-      }
-      f3 = a;
-    }
-  }
-  main() {
-    new A(true);
-    new A(false);
-  }
-""";
-
-const String TEST_19 = r"""
-  class A {
-    var f1;
-    var f2;
-    var f3;
-    A(x) {
-      f1 = 1;
-      var a;
-      if (x) {
-        f2 = "1";
-        a = this;
-      } else {
-        a = 1;
-        f2 = "1";
-      }
-      f3 = a;
-      a();
-    }
-  }
-  main() {
-    new A(true);
-    new A(false);
-  }
-""";
-
-const String TEST_20 = r"""
-  class A {
-    var f;
-    A() {
-      for (f in this) {
-      }
-    }
-    get iterator => this;
-    get current => 42;
-    bool moveNext() => false;
-  }
-  main() {
-    new A();
-  }
-""";
-
-const String TEST_21 = r"""
-  class A {
-    var f;
-    A() {
-      for (var i in this) {
-      }
-      f = 42;
-    }
-    get iterator => null;
-  }
-  main() {
-    new A();
-  }
-""";
-
-const String TEST_22 = r"""
-  class A {
-    var f1;
-    var f2;
-    var f3;
-    A() {
-      f1 = 42;
-      f2 = f1 == null ? 42 : f3 == null ? 41: 43;
-      f3 = 'foo';
-    }
-  }
-  main() {
-    new A();
-  }
-""";
-
-const String TEST_23 = r"""
-  class A {
-    var f1 = 42;
-    var f2 = 42;
-    var f3 = 42;
-    var f4 = 42;
-    A() {
-      // Test string interpolation.
-      '${f1 = null}';
-      // Test string juxtaposition.
-      ''
-      '${f2 = null}';
-      // Test list literal.
-      [f3 = null];
-      // Test map literal.
-      var c = {'foo': f4 = null };
-    }
-  }
-  main() {
-    new A();
-  }
-""";
-
-const String TEST_24 = r"""
-  class A {
-    var f1 = 42;
-    var f2 = 42;
-    var f3 = 42;
-    final f4;
-    var f5;
-    var f6 = null;
-    A() : f4 = 42 {
-      f1++;
-      f2 += 42;
-      var f6 = 'foo';
-      this.f6 = f6;
-    }
-    A.foo(other) : f3 = other.f3, f4 = other.f4, f5 = other.bar();
-    operator+(other) => 'foo';
-    bar() => 42.5;
-  }
-  class B extends A {
-    bar() => 42;
-  }
-  main() {
-    new A();
-    new A.foo(new A());
-    new A.foo(new B());
-
-  }
-""";
-
-const String TEST_25 = r"""
-  class A {
-    var f1 = 42;
-  }
-  class B {
-    var f1 = '42';
-  }
-  main() {
-    new B();
-    new A().f1 = new A().f1;
-  }
-""";
-
-const String TEST_26 = r"""
-  class A {
-    var f1 = 42;
-  }
-  class B {
-    var f1 = 54;
-  }
-  main() {
-    new A().f1 = [new B(), new A()][0].f1 + 42;
-  }
-""";
-
-const String TEST_27 = r"""
-  class A {
-    var f1;
-    var f2;
-    A() {
-      this.f1 = 42;
-      this.f2 = 42;
-    }
-  }
-  class B extends A {
-    set f2(value) {}
-  }
-  main() {
-    new A();
-    new B();
-  }
-""";
-
-const String TEST_28 = r"""
-  class A {
-    var f1;
-    var f2;
-    A(x) {
-      this.f1 = x;
-      if (x == 0) return;
-      this.f2 = x;
-    }
-  }
-  main() {
-    new A(0);
-    new A(1);
-  }
-""";
-
-const String TEST_29 = r"""
-  class A {
-    var f1;
-    var f2;
-    A(x) {
-      this.f1 = x;
-      if (x == 0) {
-      } else {
-        return;
-      }
-      this.f2 = x;
-    }
-  }
-  main() {
-    new A(0);
-    new A(1);
-  }
-""";
-
-const String TEST_30 = r"""
-  class A {
-    var f1;
-    var f2;
-    var f3;
-    A(x) {
-      this.f1 = x;
-      if (x == 0) {
-        this.f2 = 1;
-      } else {
-        this.f2 = x;
-        return;
-      }
-      this.f3 = x;
-    }
-  }
-  main() {
-    new A(0);
-    new A(1);
-  }
-""";
-
-typedef TypeMask TestCallback(ClosedWorld closedWorld);
-
-void doTest(
-    String test, bool disableInlining, Map<String, TestCallback> fields) {
-  fields.forEach((String name, TestCallback f) {
-    compileAndFind(test, 'A', name, disableInlining, (compiler, field) {
-      var inferrer = compiler.globalInference.typesInferrerInternal;
-      var closedWorld = inferrer.closedWorld;
-      TypeMask type = f(closedWorld);
-      TypeMask inferredType =
-          simplify(inferrer.getTypeOfMember(field), closedWorld);
-      Expect.equals(type, inferredType, '$name of:\n$test');
-    });
-  });
-}
-
-void runTest(String test, Map<String, TestCallback> fields) {
-  doTest(test, false, fields);
-  doTest(test, true, fields);
-}
-
-void test() {
-  runTest(TEST_1, <String, TestCallback>{
-    'f': (closedWorld) => closedWorld.commonMasks.nullType
-  });
-  runTest(TEST_2, <String, TestCallback>{
-    'f1': (closedWorld) => closedWorld.commonMasks.nullType,
-    'f2': (closedWorld) => closedWorld.commonMasks.uint31Type
-  });
-  runTest(TEST_3, <String, TestCallback>{
-    'f1': (closedWorld) => closedWorld.commonMasks.uint31Type,
-    'f2': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable()
-  });
-  runTest(TEST_4, <String, TestCallback>{
-    'f1': (closedWorld) => closedWorld.commonMasks.interceptorType,
-    'f2': (closedWorld) => closedWorld.commonMasks.stringType.nullable()
-  });
-
-  // TODO(ngeoffray): We should try to infer that the initialization
-  // code at the declaration site of the fields does not matter.
-  runTest(TEST_5, <String, TestCallback>{
-    'f1': (closedWorld) => closedWorld.commonMasks.interceptorType,
-    'f2': (closedWorld) => closedWorld.commonMasks.interceptorType,
-  });
-  runTest(TEST_6, <String, TestCallback>{
-    'f1': (closedWorld) => closedWorld.commonMasks.interceptorType,
-    'f2': (closedWorld) => closedWorld.commonMasks.interceptorType,
-  });
-  runTest(TEST_7, <String, TestCallback>{
-    'f1': (closedWorld) => closedWorld.commonMasks.interceptorType,
-    'f2': (closedWorld) => closedWorld.commonMasks.interceptorType,
-  });
-
-  runTest(TEST_8, <String, TestCallback>{
-    'f': (closedWorld) => closedWorld.commonMasks.stringType.nullable()
-  });
-  runTest(TEST_9, <String, TestCallback>{
-    'f': (closedWorld) => closedWorld.commonMasks.stringType.nullable()
-  });
-  runTest(TEST_10, <String, TestCallback>{
-    'f': (closedWorld) => closedWorld.commonMasks.uint31Type
-  });
-  runTest(TEST_11, <String, TestCallback>{
-    'fs': (closedWorld) => closedWorld.commonMasks.uint31Type
-  });
-
-  // TODO(ngeoffray): We should try to infer that the initialization
-  // code at the declaration site of the fields does not matter.
-  runTest(TEST_12, <String, TestCallback>{
-    'fs': (closedWorld) => closedWorld.commonMasks.interceptorType
-  });
-
-  runTest(TEST_13, <String, TestCallback>{
-    'fs': (closedWorld) => closedWorld.commonMasks.uint31Type
-  });
-  runTest(TEST_14, <String, TestCallback>{
-    'f': (closedWorld) => closedWorld.commonMasks.uint31Type
-  });
-  runTest(TEST_15, <String, TestCallback>{
-    'f': (closedWorld) {
-      ClassElement cls = closedWorld.commonElements.jsIndexableClass;
-      return new TypeMask.nonNullSubtype(cls, closedWorld);
-    }
-  });
-  runTest(TEST_16, <String, TestCallback>{
-    'f': (closedWorld) => closedWorld.commonMasks.interceptorType
-  });
-  runTest(TEST_17, <String, TestCallback>{
-    'f': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable()
-  });
-  runTest(TEST_18, <String, TestCallback>{
-    'f1': (closedWorld) => closedWorld.commonMasks.uint31Type,
-    'f2': (closedWorld) => closedWorld.commonMasks.stringType,
-    'f3': (closedWorld) => closedWorld.commonMasks.dynamicType
-  });
-  runTest(TEST_19, <String, TestCallback>{
-    'f1': (closedWorld) => closedWorld.commonMasks.uint31Type,
-    'f2': (closedWorld) => closedWorld.commonMasks.stringType,
-    'f3': (closedWorld) => closedWorld.commonMasks.dynamicType
-  });
-  runTest(TEST_20, <String, TestCallback>{
-    'f': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable()
-  });
-  runTest(TEST_21, <String, TestCallback>{
-    'f': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable()
-  });
-
-  runTest(TEST_22, <String, TestCallback>{
-    'f1': (closedWorld) => closedWorld.commonMasks.uint31Type,
-    'f2': (closedWorld) => closedWorld.commonMasks.uint31Type,
-    'f3': (closedWorld) => closedWorld.commonMasks.stringType.nullable()
-  });
-
-  runTest(TEST_23, <String, TestCallback>{
-    'f1': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable(),
-    'f2': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable(),
-    'f3': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable(),
-    'f4': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable()
-  });
-
-  runTest(TEST_24, <String, TestCallback>{
-    'f1': (closedWorld) => closedWorld.commonMasks.positiveIntType,
-    'f2': (closedWorld) => closedWorld.commonMasks.positiveIntType,
-    'f3': (closedWorld) => closedWorld.commonMasks.uint31Type,
-    'f4': (closedWorld) => closedWorld.commonMasks.uint31Type,
-    'f5': (closedWorld) => closedWorld.commonMasks.numType.nullable(),
-    'f6': (closedWorld) => closedWorld.commonMasks.stringType.nullable()
-  });
-
-  runTest(TEST_25, <String, TestCallback>{
-    'f1': (closedWorld) => closedWorld.commonMasks.uint31Type
-  });
-  runTest(TEST_26, <String, TestCallback>{
-    'f1': (closedWorld) => closedWorld.commonMasks.positiveIntType
-  });
-  runTest(TEST_27, <String, TestCallback>{
-    'f1': (closedWorld) => closedWorld.commonMasks.uint31Type,
-    'f2': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable()
-  });
-  runTest(TEST_28, <String, TestCallback>{
-    'f1': (closedWorld) => closedWorld.commonMasks.uint31Type,
-    'f2': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable()
-  });
-  runTest(TEST_29, <String, TestCallback>{
-    'f1': (closedWorld) => closedWorld.commonMasks.uint31Type,
-    'f2': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable()
-  });
-  runTest(TEST_30, <String, TestCallback>{
-    'f1': (closedWorld) => closedWorld.commonMasks.uint31Type,
-    'f2': (closedWorld) => closedWorld.commonMasks.uint31Type,
-    'f3': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable()
-  });
-}
-
-void main() {
-  test();
-}
diff --git a/tests/compiler/dart2js/inference/list_tracer_length_test.dart b/tests/compiler/dart2js/inference/list_tracer_length_test.dart
index 5ad3506..d5e8d72 100644
--- a/tests/compiler/dart2js/inference/list_tracer_length_test.dart
+++ b/tests/compiler/dart2js/inference/list_tracer_length_test.dart
@@ -2,7 +2,8 @@
 // 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.
 
-/// TODO(johnniwinther): Currently this only works with the mock compiler.
+/// TODO(johnniwinther): Move this to the codegen folder. Currently this only
+/// works with the mock compiler.
 
 import "package:expect/expect.dart";
 import "package:async_helper/async_helper.dart";
diff --git a/tests/compiler/dart2js/inference/list_tracer_node_type_test.dart b/tests/compiler/dart2js/inference/list_tracer_node_type_test.dart
index b1d315f..03ae59c 100644
--- a/tests/compiler/dart2js/inference/list_tracer_node_type_test.dart
+++ b/tests/compiler/dart2js/inference/list_tracer_node_type_test.dart
@@ -2,7 +2,8 @@
 // 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.
 
-/// TODO(johnniwinther): Currently this only works with the mock compiler.
+/// TODO(johnniwinther): Move this to the codegen folder. Currently this only
+/// works with the mock compiler.
 
 import "package:expect/expect.dart";
 import "package:async_helper/async_helper.dart";
diff --git a/tests/compiler/dart2js/inference/list_tracer_test.dart b/tests/compiler/dart2js/inference/list_tracer_test.dart
index b9f5e819..831ead7 100644
--- a/tests/compiler/dart2js/inference/list_tracer_test.dart
+++ b/tests/compiler/dart2js/inference/list_tracer_test.dart
@@ -5,12 +5,13 @@
 /// TODO(johnniwinther): Port this test to use the equivalence framework.
 /// Currently it only works with the mock compiler.
 
-import 'package:expect/expect.dart';
-import "package:async_helper/async_helper.dart";
+import 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/types/types.dart' show ContainerTypeMask, TypeMask;
+import 'package:compiler/src/commandline_options.dart';
+import 'package:expect/expect.dart';
 
 import 'type_mask_test_helper.dart';
-import '../compiler_helper.dart';
+import '../memory_compiler.dart';
 
 String generateTest(String listAllocation) {
   return """
@@ -189,58 +190,76 @@
 }
 
 void main() {
-  doTest('[]', nullify: false); // Test literal list.
-  doTest('new List()', nullify: false); // Test growable list.
-  doTest('new List(1)', nullify: true); // Test fixed list.
-  doTest('new List.filled(1, 0)', nullify: false); // Test List.filled.
-  doTest('new List.filled(1, null)', nullify: true); // Test List.filled.
+  runTest({bool useKernel}) async {
+    // Test literal list.
+    await doTest('[]', nullify: false, useKernel: useKernel);
+    // Test growable list.
+    await doTest('new List()', nullify: false, useKernel: useKernel);
+    // Test fixed list.
+    await doTest('new List(1)', nullify: true, useKernel: useKernel);
+    // Test List.filled.
+    await doTest('new List.filled(1, 0)', nullify: false, useKernel: useKernel);
+    // Test List.filled.
+    await doTest('new List.filled(1, null)',
+        nullify: true, useKernel: useKernel);
+  }
+
+  asyncTest(() async {
+    print('--test from ast---------------------------------------------------');
+    await runTest(useKernel: false);
+    print('--test from kernel------------------------------------------------');
+    await runTest(useKernel: true);
+  });
 }
 
-void doTest(String allocation, {bool nullify}) {
-  Uri uri = new Uri(scheme: 'source');
-  var compiler = mockCompilerFor(generateTest(allocation), uri,
-      expectedErrors: 0, expectedWarnings: 1);
-  asyncTest(() => compiler.run(uri).then((_) {
-        var typesInferrer = compiler.globalInference.typesInferrerInternal;
-        var closedWorld = typesInferrer.closedWorld;
-        var commonMasks = closedWorld.commonMasks;
+doTest(String allocation, {bool nullify, bool useKernel}) async {
+  String source = generateTest(allocation);
+  var result = await runCompiler(
+      memorySourceFiles: {'main.dart': source},
+      options: useKernel ? [Flags.useKernel] : []);
+  Expect.isTrue(result.isSuccess);
+  var compiler = result.compiler;
+  var typesInferrer = compiler.globalInference.typesInferrerInternal;
+  var closedWorld = typesInferrer.closedWorld;
+  var commonMasks = closedWorld.commonMasks;
 
-        checkType(String name, type) {
-          MemberElement element = findElement(compiler, name);
-          ContainerTypeMask mask = typesInferrer.getTypeOfMember(element);
-          if (nullify) type = type.nullable();
-          Expect.equals(type, simplify(mask.elementType, closedWorld), name);
-        }
+  checkType(String name, type) {
+    var element = findMember(closedWorld, name);
+    ContainerTypeMask mask = typesInferrer.getTypeOfMember(element);
+    if (nullify) type = type.nullable();
+    Expect.equals(type, simplify(mask.elementType, closedWorld), name);
+  }
 
-        checkType('listInField', commonMasks.numType);
-        checkType('listPassedToMethod', commonMasks.numType);
-        checkType('listReturnedFromMethod', commonMasks.numType);
-        checkType('listUsedWithCascade', commonMasks.numType);
-        checkType('listUsedInClosure', commonMasks.numType);
-        checkType('listPassedToSelector', commonMasks.numType);
-        checkType('listReturnedFromSelector', commonMasks.numType);
-        checkType('listUsedWithAddAndInsert', commonMasks.numType);
-        checkType('listUsedWithConstraint', commonMasks.positiveIntType);
-        checkType('listEscapingFromSetter', commonMasks.numType);
-        checkType('listUsedInLocal', commonMasks.numType);
-        checkType('listEscapingInSetterValue', commonMasks.numType);
-        checkType('listEscapingInIndex', commonMasks.numType);
-        checkType('listEscapingInIndexSet', commonMasks.uint31Type);
-        checkType('listEscapingTwiceInIndexSet', commonMasks.numType);
-        checkType('listSetInNonFinalField', commonMasks.numType);
-        checkType('listWithChangedLength', commonMasks.uint31Type.nullable());
+  checkType('listInField', commonMasks.numType);
+  checkType('listPassedToMethod', commonMasks.numType);
+  checkType('listReturnedFromMethod', commonMasks.numType);
+  checkType('listUsedWithCascade', commonMasks.numType);
+  checkType('listUsedInClosure', commonMasks.numType);
+  checkType('listPassedToSelector', commonMasks.numType);
+  checkType('listReturnedFromSelector', commonMasks.numType);
+  checkType('listUsedWithAddAndInsert', commonMasks.numType);
+  checkType('listUsedWithConstraint', commonMasks.positiveIntType);
+  checkType('listEscapingFromSetter', commonMasks.numType);
+  checkType('listUsedInLocal', commonMasks.numType);
+  checkType('listEscapingInSetterValue', commonMasks.numType);
+  checkType('listEscapingInIndex', commonMasks.numType);
+  checkType('listEscapingInIndexSet', commonMasks.uint31Type);
+  // TODO(johnniwinther): Since Iterable.iterableToString is part of the closed
+  // world we find the `dynamicType` instead of `numType`.
+  checkType('listEscapingTwiceInIndexSet', commonMasks.dynamicType);
+  checkType('listSetInNonFinalField', commonMasks.numType);
+  checkType('listWithChangedLength', commonMasks.uint31Type.nullable());
 
-        checkType('listPassedToClosure', commonMasks.dynamicType);
-        checkType('listReturnedFromClosure', commonMasks.dynamicType);
-        checkType('listUsedWithNonOkSelector', commonMasks.dynamicType);
-        checkType('listPassedAsOptionalParameter', commonMasks.numType);
-        checkType('listPassedAsNamedParameter', commonMasks.numType);
-        checkType('listStoredInList', commonMasks.uint31Type);
-        checkType('listStoredInListButEscapes', commonMasks.dynamicType);
+  checkType('listPassedToClosure', commonMasks.dynamicType);
+  checkType('listReturnedFromClosure', commonMasks.dynamicType);
+  checkType('listUsedWithNonOkSelector', commonMasks.dynamicType);
+  checkType('listPassedAsOptionalParameter', commonMasks.numType);
+  checkType('listPassedAsNamedParameter', commonMasks.numType);
+  checkType('listStoredInList', commonMasks.uint31Type);
+  checkType('listStoredInListButEscapes', commonMasks.dynamicType);
 
-        if (!allocation.contains('filled')) {
-          checkType('listUnset', new TypeMask.nonNullEmpty());
-          checkType('listOnlySetWithConstraint', new TypeMask.nonNullEmpty());
-        }
-      }));
+  if (!allocation.contains('filled')) {
+    checkType('listUnset', new TypeMask.nonNullEmpty());
+    checkType('listOnlySetWithConstraint', new TypeMask.nonNullEmpty());
+  }
 }
diff --git a/tests/compiler/dart2js/inference/map_tracer_keys_test.dart b/tests/compiler/dart2js/inference/map_tracer_keys_test.dart
deleted file mode 100644
index e968733..0000000
--- a/tests/compiler/dart2js/inference/map_tracer_keys_test.dart
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (c) 2014, 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.
-
-/// TODO(johnniwinther): Port this test to use the equivalence framework.
-/// Currently it only works with the mock compiler.
-
-import 'package:expect/expect.dart';
-import "package:async_helper/async_helper.dart";
-import 'package:compiler/src/types/types.dart' show ContainerTypeMask, TypeMask;
-
-import '../compiler_helper.dart';
-
-String generateTest(String key, String value, bool initial) {
-  return """
-double aDouble = 42.5;
-List aList = [42];
-
-consume(x) => x;
-
-main() {
-""" +
-      (initial
-          ? """
-  var theMap = {'a': 2.2, 'b': 3.3, 'c': 4.4, $key: $value};
-"""
-          : """
-  var theMap = {'a': 2.2, 'b': 3.3, 'c': 4.4};
-  theMap[$key] = $value;
-""") +
-      """
-  for (var key in theMap.keys) {
-    aDouble = theMap[key];
-  }
-  // We have to reference it somewhere, so that it always gets resolved.
-  consume(aList);
-}
-""";
-}
-
-void main() {
-  // Test using keys without the list floating in
-  doTest();
-  // Test using keys with the list floating in as key
-  doTest(key: "aList", bail: true);
-  // Test using keys with the list floating in as value
-  doTest(value: "aList");
-  // And the above where we add the list as part of the map literal.
-  doTest(initial: true);
-  doTest(key: "aList", bail: true, initial: true);
-  doTest(value: "aList", initial: true);
-}
-
-void doTest(
-    {String key: "'d'",
-    String value: "5.5",
-    bool bail: false,
-    bool initial: false}) {
-  Uri uri = new Uri(scheme: 'source');
-  var compiler = mockCompilerFor(generateTest(key, value, initial), uri,
-      expectedErrors: 0, expectedWarnings: 0);
-  asyncTest(() => compiler.run(uri).then((_) {
-        var typesInferrer = compiler.globalInference.typesInferrerInternal;
-        var commonMasks = typesInferrer.closedWorld.commonMasks;
-        MemberElement aDouble = findElement(compiler, 'aDouble');
-        var aDoubleType = typesInferrer.getTypeOfMember(aDouble);
-        MemberElement aList = findElement(compiler, 'aList');
-        var aListType = typesInferrer.getTypeOfMember(aList);
-
-        Expect.equals(aDoubleType, commonMasks.doubleType);
-        Expect.isTrue(aListType is ContainerTypeMask);
-        ContainerTypeMask container = aListType;
-        TypeMask elementType = container.elementType;
-        if (bail) {
-          Expect.equals(elementType, commonMasks.dynamicType);
-        } else {
-          Expect.equals(elementType, commonMasks.uint31Type);
-        }
-      }));
-}
diff --git a/tests/compiler/dart2js/inference/map_tracer_test.dart b/tests/compiler/dart2js/inference/map_tracer_test.dart
index ddac6fd..8e8309e 100644
--- a/tests/compiler/dart2js/inference/map_tracer_test.dart
+++ b/tests/compiler/dart2js/inference/map_tracer_test.dart
@@ -5,12 +5,17 @@
 /// TODO(johnniwinther): Port this test to use the equivalence framework.
 /// Currently it only works with the mock compiler.
 
-import 'package:expect/expect.dart';
-import "package:async_helper/async_helper.dart";
+import 'package:async_helper/async_helper.dart';
+import 'package:compiler/src/commandline_options.dart';
+import 'package:compiler/src/compiler.dart';
+import 'package:compiler/src/elements/entities.dart';
+import 'package:compiler/src/inferrer/type_graph_inferrer.dart';
 import 'package:compiler/src/types/types.dart' show MapTypeMask, TypeMask;
+import 'package:compiler/src/world.dart';
+import 'package:expect/expect.dart';
 
 import 'type_mask_test_helper.dart';
-import '../compiler_helper.dart';
+import '../memory_compiler.dart';
 
 String generateTest(String mapAllocation) {
   return """
@@ -119,6 +124,8 @@
 }
 
 main() {
+  anInt++;
+
   mapReturnedFromMethod[aKey] = anInt;
   bar()[aKey] = aDouble;
 
@@ -202,90 +209,103 @@
 }
 
 void main() {
-  // Test empty literal map
-  doTest('{}');
-  // Test preset map of <String,uint32>
-  doTest('{presetKey : anInt}', "presetKey", "anInt");
-  // Test preset map of <Double,uint32>
-  doTest('{aDouble : anInt}', "aDouble", "anInt");
+  runTests({bool useKernel}) async {
+    // Test empty literal map
+    await doTest('{}', useKernel: useKernel);
+    // Test preset map of <String,uint32>
+    await doTest('{presetKey : anInt}',
+        keyElementName: "presetKey",
+        valueElementName: "anInt",
+        useKernel: useKernel);
+    // Test preset map of <Double,uint32>
+    await doTest('{aDouble : anInt}',
+        keyElementName: "aDouble",
+        valueElementName: "anInt",
+        useKernel: useKernel);
+  }
+
+  asyncTest(() async {
+    print('--test from ast---------------------------------------------------');
+    await runTests(useKernel: false);
+    print('--test from kernel------------------------------------------------');
+    await runTests(useKernel: true);
+  });
 }
 
-void doTest(String allocation,
-    [String keyElementName, String valueElementName]) {
-  Uri uri = new Uri(scheme: 'source');
-  var compiler = mockCompilerFor(generateTest(allocation), uri,
-      expectedErrors: 0, expectedWarnings: 1);
-  asyncTest(() => compiler.run(uri).then((_) {
-        var keyType, valueType;
-        var typesInferrer = compiler.globalInference.typesInferrerInternal;
-        var closedWorld = typesInferrer.closedWorld;
-        var commonMasks = closedWorld.commonMasks;
-        var emptyType = new TypeMask.nonNullEmpty();
-        MemberElement aKey = findElement(compiler, 'aKey');
-        var aKeyType = typesInferrer.getTypeOfMember(aKey);
-        if (keyElementName != null) {
-          MemberElement keyElement = findElement(compiler, keyElementName);
-          keyType = typesInferrer.getTypeOfMember(keyElement);
-        }
-        if (valueElementName != null) {
-          MemberElement valueElement = findElement(compiler, valueElementName);
-          valueType = typesInferrer.getTypeOfMember(valueElement);
-        }
-        if (keyType == null) keyType = emptyType;
-        if (valueType == null) valueType = emptyType;
+doTest(String allocation,
+    {String keyElementName, String valueElementName, bool useKernel}) async {
+  String source = generateTest(allocation);
+  var result = await runCompiler(
+      memorySourceFiles: {'main.dart': source},
+      options: useKernel ? [Flags.useKernel] : []);
+  Expect.isTrue(result.isSuccess);
+  Compiler compiler = result.compiler;
+  TypeMask keyType, valueType;
+  TypeGraphInferrer typesInferrer =
+      compiler.globalInference.typesInferrerInternal;
+  ClosedWorld closedWorld = typesInferrer.closedWorld;
+  CommonMasks commonMasks = closedWorld.commonMasks;
+  TypeMask emptyType = new TypeMask.nonNullEmpty();
+  MemberEntity aKey = findMember(closedWorld, 'aKey');
+  TypeMask aKeyType = typesInferrer.getTypeOfMember(aKey);
+  if (keyElementName != null) {
+    MemberEntity keyElement = findMember(closedWorld, keyElementName);
+    keyType = typesInferrer.getTypeOfMember(keyElement);
+  }
+  if (valueElementName != null) {
+    MemberEntity valueElement = findMember(closedWorld, valueElementName);
+    valueType = typesInferrer.getTypeOfMember(valueElement);
+  }
+  if (keyType == null) keyType = emptyType;
+  if (valueType == null) valueType = emptyType;
 
-        checkType(String name, keyType, valueType) {
-          MemberElement element = findElement(compiler, name);
-          MapTypeMask mask = typesInferrer.getTypeOfMember(element);
-          Expect.equals(keyType, simplify(mask.keyType, closedWorld), name);
-          Expect.equals(valueType, simplify(mask.valueType, closedWorld), name);
-        }
+  checkType(String name, keyType, valueType) {
+    MemberEntity element = findMember(closedWorld, name);
+    MapTypeMask mask = typesInferrer.getTypeOfMember(element);
+    Expect.equals(keyType, simplify(mask.keyType, closedWorld), name);
+    Expect.equals(valueType, simplify(mask.valueType, closedWorld), name);
+  }
 
-        K(TypeMask other) =>
-            simplify(keyType.union(other, closedWorld), closedWorld);
-        V(TypeMask other) =>
-            simplify(valueType.union(other, closedWorld), closedWorld)
-                .nullable();
+  K(TypeMask other) => simplify(keyType.union(other, closedWorld), closedWorld);
+  V(TypeMask other) =>
+      simplify(valueType.union(other, closedWorld), closedWorld).nullable();
 
-        checkType('mapInField', K(aKeyType), V(commonMasks.numType));
-        checkType('mapPassedToMethod', K(aKeyType), V(commonMasks.numType));
-        checkType('mapReturnedFromMethod', K(aKeyType), V(commonMasks.numType));
-        checkType('mapUsedWithCascade', K(aKeyType), V(commonMasks.numType));
-        checkType('mapUsedInClosure', K(aKeyType), V(commonMasks.numType));
-        checkType('mapPassedToSelector', K(aKeyType), V(commonMasks.numType));
-        checkType(
-            'mapReturnedFromSelector', K(aKeyType), V(commonMasks.numType));
-        checkType(
-            'mapUsedWithConstraint', K(aKeyType), V(commonMasks.uint31Type));
-        checkType('mapEscapingFromSetter', K(aKeyType), V(commonMasks.numType));
-        checkType('mapUsedInLocal', K(aKeyType), V(commonMasks.numType));
-        checkType(
-            'mapEscapingInSetterValue', K(aKeyType), V(commonMasks.numType));
-        checkType('mapEscapingInIndex', K(aKeyType), V(commonMasks.numType));
-        checkType(
-            'mapEscapingInIndexSet', K(aKeyType), V(commonMasks.uint31Type));
-        checkType(
-            'mapEscapingTwiceInIndexSet', K(aKeyType), V(commonMasks.numType));
-        checkType('mapSetInNonFinalField', K(aKeyType), V(commonMasks.numType));
+  checkType('mapInField', K(aKeyType), V(commonMasks.numType));
+  checkType('mapPassedToMethod', K(aKeyType), V(commonMasks.numType));
+  checkType('mapReturnedFromMethod', K(aKeyType), V(commonMasks.numType));
+  checkType('mapUsedWithCascade', K(aKeyType), V(commonMasks.numType));
+  checkType('mapUsedInClosure', K(aKeyType), V(commonMasks.numType));
+  checkType('mapPassedToSelector', K(aKeyType), V(commonMasks.numType));
+  checkType('mapReturnedFromSelector', K(aKeyType), V(commonMasks.numType));
+  checkType(
+      'mapUsedWithConstraint', K(aKeyType), V(commonMasks.positiveIntType));
+  checkType('mapEscapingFromSetter', K(aKeyType), V(commonMasks.numType));
+  checkType('mapUsedInLocal', K(aKeyType), V(commonMasks.numType));
+  checkType('mapEscapingInSetterValue', K(aKeyType), V(commonMasks.numType));
+  checkType('mapEscapingInIndex', K(aKeyType), V(commonMasks.numType));
+  checkType(
+      'mapEscapingInIndexSet', K(aKeyType), V(commonMasks.positiveIntType));
+  // TODO(johnniwinther): Reenable this when we don't bail out due to
+  // (benign) JS calls.
+  //checkType('mapEscapingTwiceInIndexSet', K(aKeyType), V(commonMasks.numType));
+  checkType('mapSetInNonFinalField', K(aKeyType), V(commonMasks.numType));
 
-        checkType('mapPassedToClosure', K(commonMasks.dynamicType),
-            V(commonMasks.dynamicType));
-        checkType('mapReturnedFromClosure', K(commonMasks.dynamicType),
-            V(commonMasks.dynamicType));
-        checkType('mapUsedWithNonOkSelector', K(commonMasks.dynamicType),
-            V(commonMasks.dynamicType));
-        checkType('mapPassedAsOptionalParameter', K(aKeyType),
-            V(commonMasks.numType));
-        checkType(
-            'mapPassedAsNamedParameter', K(aKeyType), V(commonMasks.numType));
-        checkType('mapStoredInList', K(aKeyType), V(commonMasks.uint31Type));
-        checkType('mapStoredInListButEscapes', K(commonMasks.dynamicType),
-            V(commonMasks.dynamicType));
-        checkType('mapStoredInMap', K(aKeyType), V(commonMasks.uint31Type));
-        checkType('mapStoredInMapButEscapes', K(commonMasks.dynamicType),
-            V(commonMasks.dynamicType));
+  checkType('mapPassedToClosure', K(commonMasks.dynamicType),
+      V(commonMasks.dynamicType));
+  checkType('mapReturnedFromClosure', K(commonMasks.dynamicType),
+      V(commonMasks.dynamicType));
+  checkType('mapUsedWithNonOkSelector', K(commonMasks.dynamicType),
+      V(commonMasks.dynamicType));
+  checkType(
+      'mapPassedAsOptionalParameter', K(aKeyType), V(commonMasks.numType));
+  checkType('mapPassedAsNamedParameter', K(aKeyType), V(commonMasks.numType));
+  checkType('mapStoredInList', K(aKeyType), V(commonMasks.uint31Type));
+  checkType('mapStoredInListButEscapes', K(commonMasks.dynamicType),
+      V(commonMasks.dynamicType));
+  checkType('mapStoredInMap', K(aKeyType), V(commonMasks.uint31Type));
+  checkType('mapStoredInMapButEscapes', K(commonMasks.dynamicType),
+      V(commonMasks.dynamicType));
 
-        checkType('mapUnset', K(emptyType), V(emptyType));
-        checkType('mapOnlySetWithConstraint', K(aKeyType), V(emptyType));
-      }));
+  checkType('mapUnset', K(emptyType), V(emptyType));
+  checkType('mapOnlySetWithConstraint', K(aKeyType), V(emptyType));
 }
diff --git a/tests/compiler/dart2js/inference/show.dart b/tests/compiler/dart2js/inference/show.dart
index 6870b5f..3d7c465 100644
--- a/tests/compiler/dart2js/inference/show.dart
+++ b/tests/compiler/dart2js/inference/show.dart
@@ -4,9 +4,35 @@
 
 /// Helper program that shows the inferrer data on a dart program.
 
+import 'package:args/args.dart';
+import 'package:compiler/src/inferrer/inferrer_engine.dart';
+import '../equivalence/id_equivalence_helper.dart';
 import '../equivalence/show_helper.dart';
 import 'inference_test_helper.dart';
+import 'side_effects_test.dart';
+import 'callers_test.dart';
 
 main(List<String> args) async {
-  await show(args, computeMemberAstTypeMasks, computeMemberIrTypeMasks);
+  ArgParser argParser = createArgParser();
+  argParser.addFlag('inference', defaultsTo: true);
+  argParser.addFlag('side-effects', defaultsTo: false);
+  argParser.addFlag('callers', defaultsTo: false);
+  ArgResults results = argParser.parse(args);
+
+  ComputeMemberDataFunction astFunction;
+  ComputeMemberDataFunction kernelFunction;
+  if (results['side-effects']) {
+    astFunction = computeMemberAstSideEffects;
+    kernelFunction = computeMemberIrSideEffects;
+  }
+  if (results['callers']) {
+    InferrerEngineImpl.retainDataForTesting = true;
+    astFunction = computeMemberAstCallers;
+    kernelFunction = computeMemberIrCallers;
+  } else {
+    InferrerEngineImpl.useSorterForTesting = true;
+    astFunction = computeMemberAstTypeMasks;
+    kernelFunction = computeMemberIrTypeMasks;
+  }
+  await show(results, astFunction, kernelFunction);
 }
diff --git a/tests/compiler/dart2js/inference/simple_inferrer_callers_test.dart b/tests/compiler/dart2js/inference/simple_inferrer_callers_test.dart
deleted file mode 100644
index 91fd918..0000000
--- a/tests/compiler/dart2js/inference/simple_inferrer_callers_test.dart
+++ /dev/null
@@ -1,67 +0,0 @@
-// 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.
-
-/// TODO(johnniwinther): Port this test to use the equivalence framework.
-
-// Test that computation of callers of an element works when two
-// elements of the same name are being invoked in the same method.
-
-import 'package:async_helper/async_helper.dart';
-import 'package:expect/expect.dart';
-import 'package:compiler/src/common_elements.dart';
-import 'package:compiler/src/inferrer/type_graph_inferrer.dart';
-import 'package:compiler/src/world.dart' show ClosedWorld, ClosedWorldRefiner;
-
-import '../compiler_helper.dart';
-
-const String TEST = """
-class A {
-  var field;
-}
-
-class B {
-  var field;
-}
-
-main() {
-  new A().field;
-  new B().field;
-}
-""";
-
-// Create our own type inferrer to avoid clearing out the internal
-// data structures.
-class MyInferrer extends AstTypeGraphInferrer {
-  MyInferrer(compiler, closedWorld, closedWorldRefiner)
-      : super(compiler, closedWorld, closedWorldRefiner);
-  clear() {}
-}
-
-void main() {
-  Uri uri = new Uri(scheme: 'source');
-  var compiler = mockCompilerFor(TEST, uri, analyzeOnly: true);
-  asyncTest(() => compiler.run(uri).then((_) {
-        ElementEnvironment elementEnvironment =
-            compiler.frontendStrategy.elementEnvironment;
-        ClosedWorldRefiner closedWorldRefiner =
-            compiler.closeResolution(elementEnvironment.mainFunction);
-        ClosedWorld closedWorld =
-            compiler.resolutionWorldBuilder.closedWorldForTesting;
-        var inferrer =
-            new MyInferrer(compiler, closedWorld, closedWorldRefiner);
-        compiler.globalInference.typesInferrerInternal = inferrer;
-        compiler.globalInference.runGlobalTypeInference(
-            closedWorld.elementEnvironment.mainFunction,
-            closedWorld,
-            closedWorldRefiner);
-        var mainElement = findElement(compiler, 'main');
-        dynamic classA = findElement(compiler, 'A');
-        var fieldA = classA.lookupLocalMember('field');
-        dynamic classB = findElement(compiler, 'B');
-        var fieldB = classB.lookupLocalMember('field');
-
-        Expect.isTrue(inferrer.getCallersOf(fieldA).contains(mainElement));
-        Expect.isTrue(inferrer.getCallersOf(fieldB).contains(mainElement));
-      }));
-}
diff --git a/tests/compiler/dart2js/inlining/inlining_viewer.dart b/tests/compiler/dart2js/inlining/inlining_viewer.dart
index ed25d93..9ec0739 100644
--- a/tests/compiler/dart2js/inlining/inlining_viewer.dart
+++ b/tests/compiler/dart2js/inlining/inlining_viewer.dart
@@ -10,5 +10,6 @@
 
 main(List<String> args) async {
   JavaScriptBackend.cacheCodegenImpactForTesting = true;
-  await show(args, computeMemberAstInlinings, computeMemberIrInlinings);
+  await show(createArgParser().parse(args), computeMemberAstInlinings,
+      computeMemberIrInlinings);
 }