Reapply "Cleanup after removing MirrorsData" with fix

Change-Id: I4083b06ed2ea8d9e8bdc9e884803f238adb564fb
Reviewed-on: https://dart-review.googlesource.com/55420
Reviewed-by: Sigmund Cherem <sigmund@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
index 749918f..00bfaf7 100644
--- a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
+++ b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
@@ -165,7 +165,7 @@
       metadataCollector = new MetadataCollector(compiler.options,
           compiler.reporter, _emitter, backend.rtiEncoder, codegenWorldBuilder);
       typeTestRegistry = new TypeTestRegistry(compiler.options,
-          codegenWorldBuilder, closedWorld, closedWorld.elementEnvironment);
+          codegenWorldBuilder, closedWorld.elementEnvironment);
     });
   }
 
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart
index 5b74171..ee51d11 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart
@@ -12,7 +12,6 @@
 import '../../js/js.dart' as jsAst;
 import '../../js/js.dart' show js;
 import '../../js_backend/js_backend.dart' show CompoundName, Namer;
-import '../../universe/selector.dart' show Selector;
 import '../../world.dart' show ClosedWorld;
 import '../js_emitter.dart' hide Emitter, EmitterFactory;
 import '../model.dart';
@@ -117,8 +116,6 @@
       fields = container.staticFieldsForReflection;
     }
 
-    var fieldMetadata = <jsAst.Expression>[];
-    bool hasMetadata = false;
     bool fieldsAdded = false;
 
     for (Field field in fields) {
@@ -136,8 +133,6 @@
       // accessors at runtime.
       bool needsFieldsForConstructor = !emitStatics && !classIsNative;
       if (needsFieldsForConstructor || needsAccessor) {
-        dynamic metadata = new jsAst.LiteralNull();
-        fieldMetadata.add(metadata);
         List<jsAst.Literal> fieldNameParts = <jsAst.Literal>[];
         if (!needsAccessor) {
           // Emit field for constructor generation.
@@ -179,9 +174,6 @@
       }
     }
 
-    if (hasMetadata) {
-      builder.fieldMetadata = fieldMetadata;
-    }
     return fieldsAdded;
   }
 
@@ -196,8 +188,6 @@
       jsAst.Name setterName = method.name;
       compiler.dumpInfoTask
           .registerEntityAst(member, builder.addProperty(setterName, code));
-      generateReflectionDataForFieldGetterOrSetter(member, setterName, builder,
-          isGetter: false);
     }
   }
 
@@ -347,17 +337,4 @@
         .cspPrecompiledFunctionFor(outputUnit)
         .add(js('#.prototype.# = #', [className, setterName, function]));
   }
-
-  void generateReflectionDataForFieldGetterOrSetter(
-      MemberEntity member, jsAst.Name name, ClassBuilder builder,
-      {bool isGetter}) {
-    Selector selector = isGetter
-        ? new Selector.getter(member.memberName.getter)
-        : new Selector.setter(member.memberName.setter);
-    String reflectionName = emitter.getReflectionSelectorName(selector, name);
-    if (reflectionName != null) {
-      var reflectable = js('0');
-      builder.addPropertyByName('+$reflectionName', reflectable);
-    }
-  }
 }
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/container_builder.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/container_builder.dart
index c129e62..ae9d3a7 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/container_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/container_builder.dart
@@ -6,7 +6,6 @@
 
 import '../../deferred_load.dart' show OutputUnit;
 import '../../elements/entities.dart';
-import '../../elements/entity_utils.dart' as utils;
 import '../../elements/names.dart';
 import '../../js/js.dart' as jsAst;
 import '../../js/js.dart' show js;
@@ -29,15 +28,12 @@
     jsAst.Expression code = method.code;
     bool needsStubs = method.parameterStubs.isNotEmpty;
     bool canBeApplied = method.canBeApplied;
-    bool canBeReflected = method.canBeReflected;
     bool canTearOff = method.needsTearOff;
     jsAst.Name tearOffName = method.tearOffName;
-    bool isClosure = method is InstanceMethod && method.isClosureCallMethod;
     jsAst.Name superAlias = method is InstanceMethod ? method.aliasName : null;
     bool hasSuperAlias = superAlias != null;
     jsAst.Expression memberTypeExpression = method.functionType;
-    bool needStructuredInfo =
-        canTearOff || canBeReflected || canBeApplied || hasSuperAlias;
+    bool needStructuredInfo = canTearOff || canBeApplied || hasSuperAlias;
 
     bool isIntercepted = false;
     if (method is InstanceMethod) {
@@ -99,8 +95,7 @@
 
     expressions.add(code);
 
-    bool onlyNeedsSuperAlias =
-        !(canTearOff || canBeReflected || canBeApplied || needsStubs);
+    bool onlyNeedsSuperAlias = !(canTearOff || canBeApplied || needsStubs);
 
     if (onlyNeedsSuperAlias) {
       jsAst.ArrayInitializer arrayInit =
@@ -152,7 +147,7 @@
       ..add(js.number(optionalParameterCount))
       ..add(memberTypeExpression == null ? js("null") : memberTypeExpression);
 
-    if (canBeReflected || canBeApplied) {
+    if (canBeApplied) {
       expressions.addAll(
           task.metadataCollector.reifyDefaultArguments(member, outputUnit));
 
@@ -161,21 +156,7 @@
       });
     }
     Name memberName = member.memberName;
-    if (canBeReflected) {
-      jsAst.LiteralString reflectionName;
-      if (member.isConstructor) {
-        // TODO(herhut): This registers name as a mangled name. Do we need this
-        //               given that we use a different name below?
-        emitter.getReflectionMemberName(member, name);
-        reflectionName = new jsAst.LiteralString(
-            '"new ${utils.reconstructConstructorName(member)}"');
-      } else {
-        reflectionName = js.string(namer.privateName(memberName));
-      }
-      expressions..add(reflectionName);
-    } else if (isClosure && canBeApplied) {
-      expressions.add(js.string(namer.privateName(memberName)));
-    }
+    expressions.add(js.string(namer.privateName(memberName)));
 
     jsAst.ArrayInitializer arrayInit =
         new jsAst.ArrayInitializer(expressions.toList());
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
index 5081173..bdc35cd 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
@@ -4,7 +4,6 @@
 
 library dart2js.js_emitter.full_emitter;
 
-import 'dart:collection' show HashMap;
 import 'dart:convert';
 
 import 'package:js_runtime/shared/embedded_names.dart' as embeddedNames;
@@ -18,8 +17,6 @@
 import '../../common_elements.dart' show CommonElements, ElementEnvironment;
 import '../../deferred_load.dart' show OutputUnit, OutputUnitData;
 import '../../elements/entities.dart';
-import '../../elements/entity_utils.dart' as utils;
-import '../../elements/names.dart';
 import '../../hash/sha1.dart' show Hasher;
 import '../../io/code_output.dart';
 import '../../io/location_provider.dart' show LocationCollector;
@@ -27,10 +24,9 @@
 import '../../js/js.dart' as jsAst;
 import '../../js/js.dart' show js;
 import '../../js_backend/js_backend.dart'
-    show ConstantEmitter, JavaScriptBackend, Namer, SetterName;
+    show ConstantEmitter, JavaScriptBackend, Namer;
 import '../../js_backend/native_data.dart';
 import '../../universe/call_structure.dart' show CallStructure;
-import '../../universe/selector.dart' show Selector;
 import '../../universe/world_builder.dart' show CodegenWorldBuilder;
 import '../../util/uri_extras.dart' show relativize;
 import '../../world.dart' show ClosedWorld;
@@ -117,11 +113,6 @@
   Map<OutputUnit, CodeOutput> outputBuffers = new Map<OutputUnit, CodeOutput>();
 
   String classesCollector;
-  final Map<jsAst.Name, String> mangledFieldNames =
-      new HashMap<jsAst.Name, String>();
-  final Map<jsAst.Name, String> mangledGlobalFieldNames =
-      new HashMap<jsAst.Name, String>();
-  final Set<jsAst.Name> recordedMangledNames = new Set<jsAst.Name>();
 
   JavaScriptBackend get backend => compiler.backend;
 
@@ -407,121 +398,17 @@
   /// An anonymous mixin application has no reflection name.
   ///
   /// This is used by js_mirrors.dart.
+  // TODO(johnniwinther): Do we still need this when js_mirrors is deleted?
   String getReflectionClassName(ClassEntity cls, jsAst.Name mangledName) {
-    String name = cls.name;
-    if ( // Make sure to retain names of common native types.
-        _isNativeTypeNeedingReflectionName(cls)) {
-      // TODO(ahe): Enable the next line when I can tell the difference between
-      // an instance method and a global.  They may have the same mangled name.
-      // if (recordedMangledNames.contains(mangledName)) return null;
-      recordedMangledNames.add(mangledName);
-      if (cls.isClosure) {
-        // Closures are synthesized and their name might conflict with existing
-        // globals. Assign an illegal name, and make sure they don't clash
-        // with each other.
-        return " $name";
-      }
-      if (_elementEnvironment.isUnnamedMixinApplication(cls)) return null;
+    // Make sure to retain names of common native types.
+    if (_isNativeTypeNeedingReflectionName(cls)) {
+      assert(!cls.isClosure);
+      assert(!_elementEnvironment.isUnnamedMixinApplication(cls));
       return cls.name;
     }
     return null;
   }
 
-  /// Returns the "reflection name" of a [MemberEntity], if needed.
-  ///
-  /// The reflection name of a getter 'foo' is 'foo'.
-  /// The reflection name of a setter 'foo' is 'foo='.
-  /// The reflection name of a method 'foo' is 'foo:N:M:O', where N is the
-  /// number of required arguments, M is the number of optional arguments, and
-  /// O is the named arguments.
-  /// The reflection name of a constructor is similar to a regular method but
-  /// starts with 'new '.
-  ///
-  /// This is used by js_mirrors.dart.
-  String getReflectionMemberName(MemberEntity member, jsAst.Name mangledName) {
-    return null;
-  }
-
-  String getReflectionMemberNameInternal(
-      MemberEntity member, jsAst.Name mangledName) {
-    if (member is ConstructorBodyEntity) {
-      return null;
-    }
-    if (member.isGetter) {
-      return _getReflectionGetterName(member.memberName);
-    } else if (member.isSetter) {
-      return _getReflectionSetterName(member.memberName, mangledName);
-    } else if (member.isConstructor) {
-      ConstructorEntity constructor = member;
-      String name = utils.reconstructConstructorName(constructor);
-      return _getReflectionCallStructureName(
-          name, constructor.parameterStructure.callStructure);
-    } else if (member.isFunction) {
-      FunctionEntity function = member;
-      return _getReflectionFunctionName(
-          member.memberName, function.parameterStructure.callStructure);
-    }
-    throw reporter.internalError(
-        member, 'Do not know how to reflect on this $member.');
-  }
-
-  /// Returns the "reflection name" of a [Selector], if needed.
-  ///
-  /// The reflection name of a getter 'foo' is 'foo'.
-  /// The reflection name of a setter 'foo' is 'foo='.
-  /// The reflection name of a method 'foo' is 'foo:N:M:O', where N is the
-  /// number of required arguments, M is the number of optional arguments, and
-  /// O is the named arguments.
-  ///
-  /// This is used by js_mirrors.dart.
-  String getReflectionSelectorName(Selector selector, jsAst.Name mangledName) {
-    return null;
-  }
-
-  /// Returns the "reflection name" of a [TypedefEntity], if needed.
-  ///
-  /// The reflection name of typedef 'F' is 'F'.
-  ///
-  /// This is used by js_mirrors.dart.
-  String getReflectionTypedefName(
-      TypedefEntity typedef, jsAst.Name mangledName) {
-    return null;
-  }
-
-  String _getReflectionGetterName(Name memberName) {
-    return namer.privateName(memberName);
-  }
-
-  String _getReflectionSetterName(Name memberName, jsAst.Name mangledName) {
-    String name = namer.privateName(memberName);
-    if (mangledName is! SetterName) return '$name=';
-    SetterName setterName = mangledName;
-    jsAst.Name base = setterName.base;
-    jsAst.Name getter = namer.deriveGetterName(base);
-    mangledFieldNames.putIfAbsent(getter, () => name);
-    assert(mangledFieldNames[getter] == name);
-    recordedMangledNames.add(getter);
-    // TODO(karlklose,ahe): we do not actually need to store information
-    // about the name of this setter in the output, but it is needed for
-    // marking the function as invokable by reflection.
-    return '$name=';
-  }
-
-  String _getReflectionFunctionName(
-      Name memberName, CallStructure callStructure) {
-    String name = namer.privateName(memberName);
-    return _getReflectionCallStructureName(name, callStructure);
-  }
-
-  String _getReflectionCallStructureName(
-      String name, CallStructure callStructure,
-      {bool isConstructor: false}) {
-    int positionalParameterCount = callStructure.positionalArgumentCount;
-    String namedArguments = namedParametersAsReflectionNames(callStructure);
-    String suffix = '$name:$positionalParameterCount$namedArguments';
-    return isConstructor ? 'new $suffix' : suffix;
-  }
-
   String namedParametersAsReflectionNames(CallStructure structure) {
     if (structure.isUnnamed) return '';
     String names = structure.getOrderedNamedArguments().join(':');
@@ -1157,39 +1044,6 @@
     return new jsAst.Block(parts);
   }
 
-  jsAst.Statement buildMangledNames() {
-    List<jsAst.Statement> parts = <jsAst.Statement>[];
-
-    if (!mangledFieldNames.isEmpty) {
-      List<jsAst.Name> keys = mangledFieldNames.keys.toList()..sort();
-      var properties = [];
-      for (jsAst.Name key in keys) {
-        var value = js.string(mangledFieldNames[key]);
-        properties.add(new jsAst.Property(key, value));
-      }
-
-      jsAst.Expression mangledNamesAccess =
-          generateEmbeddedGlobalAccess(embeddedNames.MANGLED_NAMES);
-      var map = new jsAst.ObjectInitializer(properties);
-      parts.add(js.statement('# = #', [mangledNamesAccess, map]));
-    }
-
-    if (!mangledGlobalFieldNames.isEmpty) {
-      List<jsAst.Name> keys = mangledGlobalFieldNames.keys.toList()..sort();
-      List<jsAst.Property> properties = <jsAst.Property>[];
-      for (jsAst.Name key in keys) {
-        jsAst.Literal value = js.string(mangledGlobalFieldNames[key]);
-        properties.add(new jsAst.Property(js.quoteName(key), value));
-      }
-      jsAst.Expression mangledGlobalNamesAccess =
-          generateEmbeddedGlobalAccess(embeddedNames.MANGLED_GLOBAL_NAMES);
-      jsAst.ObjectInitializer map = new jsAst.ObjectInitializer(properties);
-      parts.add(js.statement('# = #', [mangledGlobalNamesAccess, map]));
-    }
-
-    return new jsAst.Block(parts);
-  }
-
   void checkEverythingEmitted(
       Map<ClassEntity, ClassBuilder> pendingClassBuilders) {
     if (pendingClassBuilders == null) return;
@@ -1320,8 +1174,6 @@
 
        init();
 
-       #mangledNames;
-
        #cspPrecompiledFunctions;
 
        #setupProgram;
@@ -1389,7 +1241,6 @@
       "isolatePropertiesName": js(isolatePropertiesName),
       "initName": initName,
       "functionThatReturnsNull": buildFunctionThatReturnsNull(),
-      "mangledNames": buildMangledNames(),
       "setupProgram": buildSetupProgram(
           program, compiler, backend, namer, this, _closedWorld),
       "setupProgramName": setupProgramName,
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/nsm_emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/nsm_emitter.dart
index 29706e6..48af9c9 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/nsm_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/nsm_emitter.dart
@@ -51,31 +51,18 @@
     List<jsAst.Name> names = addedJsNames.keys.toList()..sort();
     for (jsAst.Name jsName in names) {
       Selector selector = addedJsNames[jsName];
-      String reflectionName =
-          emitter.getReflectionSelectorName(selector, jsName);
-
-      if (reflectionName != null) {
-        emitter.mangledFieldNames[jsName] = reflectionName;
-      }
-
       List<jsAst.Expression> argNames = selector.callStructure
           .getOrderedNamedArguments()
           .map((String name) => js.string(name))
           .toList();
       int type = selector.invocationMirrorKind;
       if (!haveVeryFewNoSuchMemberHandlers &&
-          isTrivialNsmHandler(type, argNames, selector, jsName) &&
-          reflectionName == null) {
+          isTrivialNsmHandler(type, argNames, selector, jsName)) {
         trivialNsmHandlers.add(selector);
       } else {
         StubMethod method =
             generator.generateStubForNoSuchMethod(jsName, selector);
         addProperty(method.name, method.code);
-        if (reflectionName != null) {
-          bool accessible = false;
-          addProperty(
-              namer.asName('+$reflectionName'), js(accessible ? '2' : '0'));
-        }
       }
     }
   }
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart
index f529482..f5a6d47 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart
@@ -65,10 +65,8 @@
   String defaultValuesField = namer.defaultValuesField;
   String methodsWithOptionalArgumentsField =
       namer.methodsWithOptionalArgumentsField;
-  bool retainMetadata = false;
-  String unmangledNameIndex = retainMetadata
-      ? ' 3 * optionalParameterCount + 2 * requiredParameterCount + 3'
-      : ' 2 * optionalParameterCount + requiredParameterCount + 3';
+  String unmangledNameIndex =
+      ' 2 * optionalParameterCount + requiredParameterCount + 3';
   String receiverParamName =
       compiler.options.enableMinification ? "r" : "receiver";
   String valueParamName = compiler.options.enableMinification ? "v" : "value";
@@ -104,7 +102,6 @@
     'deferredAction': namer.deferredAction,
     'allClasses': allClassesAccess,
     'debugFastObjects': DEBUG_FAST_OBJECTS,
-    'isTreeShakingDisabled': false,
     'precompiled': precompiledAccess,
     'finishedClassesAccess': finishedClassesAccess,
     'needsMixinSupport': emitter.needsMixinSupport,
@@ -116,7 +113,6 @@
     'isObject': namer.operatorIs(closedWorld.commonElements.objectClass),
     'specProperty': js.string(namer.nativeSpecProperty),
     'trivialNsmHandlers': emitter.buildTrivialNsmHandlers(),
-    'hasRetainedMetadata': false,
     'types': typesAccess,
     'objectClassName': js.quoteName(
         namer.runtimeTypeName(closedWorld.commonElements.objectClass)),
@@ -309,8 +305,6 @@
         var desc = processedClasses.collected[cls];
         var globalObject = desc[0];
         desc = desc[1];
-        if (#isTreeShakingDisabled)
-          constructor["${namer.metadataField}"] = desc;
         allClasses[cls] = constructor;
         globalObject[cls] = constructor;
       }
@@ -520,11 +514,6 @@
       var classData = descriptor["${namer.classDescriptorProperty}"],
           split, supr, fields = classData;
 
-      if (#hasRetainedMetadata)
-        if (typeof classData == "object" &&
-            classData instanceof Array) {
-          classData = fields = classData[0];
-        }
       // ${ClassBuilder.fieldEncodingDescription}.
       var s = fields.split(";");
       fields = s[1] ? s[1].split(",") : [];
@@ -664,14 +653,6 @@
           ${readInt("array", "position")} =
               ${readInt("array", "position")} + metadataOffset;
           position++;
-          if ($retainMetadata) {
-            var metaArray = ${readInt("array", "position")};
-            for (var j = 0; j < metaArray.length; j++) {
-              ${readInt("metaArray", "j")} =
-                ${readInt("metaArray", "j")} + metadataOffset;
-            }
-            position++;
-          }
         }
       }
       var unmangledNameIndex = $unmangledNameIndex;
diff --git a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
index b11d437..b0e6d88 100644
--- a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
+++ b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
@@ -67,43 +67,6 @@
   int compareTo(covariant _MetadataEntry other) => other._rc - this._rc;
 }
 
-abstract class Placeholder implements jsAst.DeferredNumber {
-  bind(_MetadataEntry entry);
-}
-
-class _ForwardingMetadataEntry extends _MetadataEntry implements Placeholder {
-  _MetadataEntry _forwardTo;
-  var debug;
-
-  bool get isBound => _forwardTo != null;
-
-  _ForwardingMetadataEntry([this.debug]);
-
-  _MetadataEntry get forwardTo {
-    assert(isBound, 'unbound $this $debug');
-    return _forwardTo;
-  }
-
-  jsAst.Expression get entry {
-    return forwardTo.entry;
-  }
-
-  int get value {
-    return forwardTo.value;
-  }
-
-  int get _rc => forwardTo._rc;
-
-  markSeen(jsAst.BaseVisitor visitor) => forwardTo.markSeen(visitor);
-
-  int compareTo(other) => forwardTo.compareTo(other);
-
-  bind(_MetadataEntry entry) {
-    assert(!isBound);
-    _forwardTo = entry;
-  }
-}
-
 class _MetadataList extends jsAst.DeferredExpression {
   jsAst.Expression _value;
 
@@ -155,13 +118,6 @@
   Map<OutputUnit, Map<DartType, _BoundMetadataEntry>> _typesMap =
       <OutputUnit, Map<DartType, _BoundMetadataEntry>>{};
 
-  /**
-   *  Maps a TypeVariableType to the index pointing to the constant representing
-   *  the corresponding type variable at runtime.
-   */
-  Map<TypeVariableEntity, jsAst.Expression> _typeVariableConstants =
-      new Map<TypeVariableEntity, jsAst.Expression>();
-
   MetadataCollector(this._options, this.reporter, this._emitter,
       this._rtiEncoder, this._codegenWorldBuilder);
 
@@ -178,10 +134,8 @@
     return defaultValues;
   }
 
-  jsAst.Expression reifyType(DartType type, OutputUnit outputUnit,
-      {ignoreTypeVariables: false}) {
-    return addTypeInOutputUnit(type, outputUnit,
-        ignoreTypeVariables: ignoreTypeVariables);
+  jsAst.Expression reifyType(DartType type, OutputUnit outputUnit) {
+    return addTypeInOutputUnit(type, outputUnit);
   }
 
   jsAst.Expression reifyName(String name, OutputUnit outputUnit) {
@@ -193,26 +147,6 @@
     return _addGlobalMetadata(expression, outputUnit);
   }
 
-  Placeholder _getMetadataPlaceholder([debug]) {
-    return new _ForwardingMetadataEntry(debug);
-  }
-
-  /**
-   * Returns the index pointing to the constant in [emitter.metadataCollector]
-   * representing this type variable.
-   *
-   * If the constant has not yet been constructed, an entry is  allocated in
-   * the global metadata list and the index pointing to this entry is returned.
-   * When the corresponding constant is constructed later,
-   * [reifyTypeVariableConstant] will be called and the constant will be added
-   * on the allocated entry.
-   */
-  jsAst.Expression _reifyTypeVariable(TypeVariableEntity variable) {
-    return _typeVariableConstants.putIfAbsent(variable, () {
-      return _getMetadataPlaceholder(variable);
-    });
-  }
-
   _MetadataEntry _addGlobalMetadata(jsAst.Node node, OutputUnit outputUnit) {
     String nameToKey(jsAst.Name name) => "${name.key}";
     String printed = jsAst.prettyPrint(node,
@@ -224,12 +158,14 @@
     });
   }
 
-  jsAst.Expression _computeTypeRepresentation(DartType type,
-      {ignoreTypeVariables: false}) {
+  jsAst.Expression _computeTypeRepresentation(DartType type) {
     jsAst.Expression representation =
         _rtiEncoder.getTypeRepresentation(_emitter, type, (variable) {
-      if (ignoreTypeVariables) return new jsAst.LiteralNull();
-      return _reifyTypeVariable(variable.element);
+      failedAt(
+          NO_LOCATION_SPANNABLE,
+          "Type representation for type variable $variable in "
+          "$type is not supported.");
+      return jsAst.LiteralNull();
     }, (TypedefType typedef) {
       return false;
     });
@@ -244,28 +180,15 @@
     return representation;
   }
 
-  jsAst.Expression addTypeInOutputUnit(DartType type, OutputUnit outputUnit,
-      {ignoreTypeVariables: false}) {
+  jsAst.Expression addTypeInOutputUnit(DartType type, OutputUnit outputUnit) {
     _typesMap[outputUnit] ??= new Map<DartType, _BoundMetadataEntry>();
     return _typesMap[outputUnit].putIfAbsent(type, () {
-      return new _BoundMetadataEntry(_computeTypeRepresentation(type,
-          ignoreTypeVariables: ignoreTypeVariables));
+      return new _BoundMetadataEntry(_computeTypeRepresentation(type));
     });
   }
 
   @override
   void finalizeTokens() {
-    bool checkTokensInTypes(OutputUnit outputUnit, entries) {
-      UnBoundDebugger debugger = new UnBoundDebugger(outputUnit);
-      for (_BoundMetadataEntry entry in entries) {
-        if (!entry.isUsed) continue;
-        if (debugger.findUnboundPlaceholders(entry.entry)) {
-          return false;
-        }
-      }
-      return true;
-    }
-
     void countTokensInTypes(Iterable<_BoundMetadataEntry> entries) {
       jsAst.TokenCounter counter = new jsAst.TokenCounter();
       entries
@@ -304,7 +227,6 @@
     _typesTokens.forEach((OutputUnit outputUnit, _MetadataList token) {
       Map typesMap = _typesMap[outputUnit];
       if (typesMap != null) {
-        assert(checkTokensInTypes(outputUnit, typesMap.values));
         countTokensInTypes(typesMap.values);
         token.setExpression(finalizeMap(typesMap));
       } else {
@@ -313,22 +235,3 @@
     });
   }
 }
-
-class UnBoundDebugger extends jsAst.BaseVisitor {
-  OutputUnit outputUnit;
-  bool _foundUnboundToken = false;
-
-  UnBoundDebugger(this.outputUnit);
-
-  @override
-  visitDeferredNumber(jsAst.DeferredNumber token) {
-    if (token is _ForwardingMetadataEntry && !token.isBound) {
-      _foundUnboundToken = true;
-    }
-  }
-
-  bool findUnboundPlaceholders(jsAst.Node node) {
-    node.accept(this);
-    return _foundUnboundToken;
-  }
-}
diff --git a/pkg/compiler/lib/src/js_emitter/model.dart b/pkg/compiler/lib/src/js_emitter/model.dart
index a66b830..3938cfb 100644
--- a/pkg/compiler/lib/src/js_emitter/model.dart
+++ b/pkg/compiler/lib/src/js_emitter/model.dart
@@ -21,11 +21,6 @@
   /// A map from load id to the list of fragments that need to be loaded.
   final Map<String, List<Fragment>> loadMap;
 
-  /// A map from names to strings.
-  ///
-  /// This map is needed to support `const Symbol` expressions;
-  final Map<js.Name, String> symbolsMap;
-
   // If this field is not `null` then its value must be emitted in the embedded
   // global `TYPE_TO_INTERCEPTOR_MAP`. The map references constants and classes.
   final js.Expression typeToInterceptorMap;
@@ -35,8 +30,8 @@
   final MetadataCollector _metadataCollector;
   final Iterable<js.TokenFinalizer> finalizers;
 
-  Program(this.fragments, this.holders, this.loadMap, this.symbolsMap,
-      this.typeToInterceptorMap, this._metadataCollector, this.finalizers,
+  Program(this.fragments, this.holders, this.loadMap, this.typeToInterceptorMap,
+      this._metadataCollector, this.finalizers,
       {this.needsNativeSupport,
       this.outputContainsConstantList,
       this.hasSoftDeferredClasses}) {
@@ -430,9 +425,8 @@
   final js.Name tearOffName;
   final List<ParameterStubMethod> parameterStubs;
   final bool canBeApplied;
-  final bool canBeReflected;
 
-  // Is non-null if [needsTearOff] or [canBeReflected].
+  // Is non-null if [needsTearOff].
   //
   // If the type is encoded in the metadata table this field contains an index
   // into the table. Otherwise the type contains type variables in which case
@@ -440,7 +434,7 @@
   final js.Expression functionType;
 
   // Signature information for this method. This is only required and stored
-  // here if the method [canBeApplied] or [canBeReflected]
+  // here if the method [canBeApplied].
   final int requiredParameterCount;
   final /* Map | List */ optionalParameterDefaultValues;
 
@@ -454,7 +448,6 @@
       {this.needsTearOff,
       this.tearOffName,
       this.canBeApplied,
-      this.canBeReflected,
       this.requiredParameterCount,
       this.optionalParameterDefaultValues,
       this.functionType})
@@ -462,8 +455,7 @@
     assert(needsTearOff != null);
     assert(!needsTearOff || tearOffName != null);
     assert(canBeApplied != null);
-    assert(canBeReflected != null);
-    assert((!canBeReflected && !canBeApplied) ||
+    assert(!canBeApplied ||
         (requiredParameterCount != null &&
             optionalParameterDefaultValues != null));
   }
@@ -492,7 +484,6 @@
       js.Name tearOffName,
       this.aliasName,
       bool canBeApplied,
-      bool canBeReflected,
       int requiredParameterCount,
       /* List | Map */ optionalParameterDefaultValues,
       this.isClosureCallMethod,
@@ -502,7 +493,6 @@
             needsTearOff: needsTearOff,
             tearOffName: tearOffName,
             canBeApplied: canBeApplied,
-            canBeReflected: canBeReflected,
             requiredParameterCount: requiredParameterCount,
             optionalParameterDefaultValues: optionalParameterDefaultValues,
             functionType: functionType) {
@@ -573,7 +563,6 @@
       {bool needsTearOff,
       js.Name tearOffName,
       bool canBeApplied,
-      bool canBeReflected,
       int requiredParameterCount,
       /* List | Map */ optionalParameterDefaultValues,
       js.Expression functionType})
@@ -581,7 +570,6 @@
             needsTearOff: needsTearOff,
             tearOffName: tearOffName,
             canBeApplied: canBeApplied,
-            canBeReflected: canBeReflected,
             requiredParameterCount: requiredParameterCount,
             optionalParameterDefaultValues: optionalParameterDefaultValues,
             functionType: functionType);
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart b/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
index 97afc40..615835e 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
@@ -279,14 +279,8 @@
         // TODO(johnniwinther): This should be accessed from a codegen closed
         // world.
         _worldBuilder.allReferencedStaticFields.where((FieldEntity field) {
-      if (!field.isConst) {
-        return field.isAssignable &&
-            _worldBuilder.hasConstantFieldInitializer(field);
-      } else {
-        // We also need to emit static const fields if they are available for
-        // reflection.
-        return false;
-      }
+      return field.isAssignable &&
+          _worldBuilder.hasConstantFieldInitializer(field);
     });
 
     _sorter.sortMembers(fields).forEach((MemberEntity e) => addToOutputUnit(e));
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
index 69a78e9..1ff0170 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
@@ -162,13 +162,6 @@
   /// update field-initializers to point to the ConstantModel.
   final Map<ConstantValue, Constant> _constants = <ConstantValue, Constant>{};
 
-  /// Mapping from names to strings.
-  ///
-  /// This mapping is used to support `const Symbol` expressions.
-  ///
-  /// This map is filled when building classes.
-  final Map<js.Name, String> _symbolsMap = <js.Name, String>{};
-
   Set<Class> _unneededNativeClasses;
 
   /// Classes that have been allocated during a profile run.
@@ -264,7 +257,7 @@
       finalizers.add(namingFinalizer as js.TokenFinalizer);
     }
 
-    return new Program(fragments, holders, _buildLoadMap(), _symbolsMap,
+    return new Program(fragments, holders, _buildLoadMap(),
         _buildTypeToInterceptorMap(), _task.metadataCollector, finalizers,
         needsNativeSupport: needsNativeSupport,
         outputContainsConstantList: collector.outputContainsConstantList,
@@ -878,7 +871,6 @@
     bool isNotApplyTarget =
         !element.isFunction || element.isGetter || element.isSetter;
 
-    bool canBeReflected = false;
     bool canBeApplied = _methodCanBeApplied(element);
 
     js.Name aliasName = _superMemberData.isAliasedSuperMember(element)
@@ -893,8 +885,7 @@
         isClosureCallMethod = true;
       } else {
         // Careful with operators.
-        canTearOff = _worldBuilder.hasInvokedGetter(element, _closedWorld) ||
-            (canBeReflected && !Selector.isOperatorName(element.name));
+        canTearOff = _worldBuilder.hasInvokedGetter(element, _closedWorld);
         assert(canTearOff ||
             !_worldBuilder.methodsNeedingSuperGetter.contains(element));
         tearOffName = _namer.getterForElement(element);
@@ -918,14 +909,14 @@
 
     DartType memberType = _elementEnvironment.getFunctionType(element);
     js.Expression functionType;
-    if (canTearOff || canBeReflected) {
+    if (canTearOff) {
       OutputUnit outputUnit = _outputUnitData.outputUnitForMember(element);
       functionType = _generateFunctionType(memberType, outputUnit);
     }
 
     int requiredParameterCount;
     var /* List | Map */ optionalParameterDefaultValues;
-    if (canBeApplied || canBeReflected) {
+    if (canBeApplied) {
       // TODO(redemption): Handle function entities.
       FunctionEntity method = element;
       ParameterStructure parameterStructure = method.parameterStructure;
@@ -941,7 +932,6 @@
         isIntercepted: isIntercepted,
         aliasName: aliasName,
         canBeApplied: canBeApplied,
-        canBeReflected: canBeReflected,
         requiredParameterCount: requiredParameterCount,
         optionalParameterDefaultValues: optionalParameterDefaultValues,
         functionType: functionType);
@@ -1118,11 +1108,9 @@
     bool isApplyTarget =
         !element.isConstructor && !element.isGetter && !element.isSetter;
     bool canBeApplied = _methodCanBeApplied(element);
-    bool canBeReflected = false;
 
     bool needsTearOff = isApplyTarget &&
-        (canBeReflected ||
-            _worldBuilder.staticFunctionsNeedingGetter.contains(element));
+        _worldBuilder.staticFunctionsNeedingGetter.contains(element);
 
     js.Name tearOffName =
         needsTearOff ? _namer.staticClosureName(element) : null;
@@ -1135,14 +1123,14 @@
     }
     js.Expression functionType;
     DartType type = _elementEnvironment.getFunctionType(element);
-    if (needsTearOff || canBeReflected) {
+    if (needsTearOff) {
       OutputUnit outputUnit = _outputUnitData.outputUnitForMember(element);
       functionType = _generateFunctionType(type, outputUnit);
     }
 
     int requiredParameterCount;
     var /* List | Map */ optionalParameterDefaultValues;
-    if (canBeApplied || canBeReflected) {
+    if (canBeApplied) {
       // TODO(redemption): Support entities;
       FunctionEntity method = element;
       ParameterStructure parameterStructure = method.parameterStructure;
@@ -1157,7 +1145,6 @@
         needsTearOff: needsTearOff,
         tearOffName: tearOffName,
         canBeApplied: canBeApplied,
-        canBeReflected: canBeReflected,
         requiredParameterCount: requiredParameterCount,
         optionalParameterDefaultValues: optionalParameterDefaultValues,
         functionType: functionType);
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
index cd85f8f..6996a89 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
@@ -1404,13 +1404,10 @@
     // The [MANGLED_NAMES] table must contain the mapping for const symbols.
     // Without const symbols, the table is only relevant for reflection and
     // therefore unused in this emitter.
-    List<js.Property> mangledNamesProperties = <js.Property>[];
-    program.symbolsMap.forEach((js.Name mangledName, String unmangledName) {
-      mangledNamesProperties
-          .add(new js.Property(mangledName, js.string(unmangledName)));
-    });
-    globals.add(new js.Property(js.string(MANGLED_NAMES),
-        new js.ObjectInitializer(mangledNamesProperties)));
+    // TODO(johnniwinther): Remove the need for adding an empty list of
+    // mangled names.
+    globals.add(new js.Property(
+        js.string(MANGLED_NAMES), new js.ObjectInitializer(<js.Property>[])));
 
     globals.add(emitGetTypeFromName());
 
diff --git a/pkg/compiler/lib/src/js_emitter/type_test_registry.dart b/pkg/compiler/lib/src/js_emitter/type_test_registry.dart
index 33716d4..f353ebb 100644
--- a/pkg/compiler/lib/src/js_emitter/type_test_registry.dart
+++ b/pkg/compiler/lib/src/js_emitter/type_test_registry.dart
@@ -7,7 +7,6 @@
 import '../common.dart';
 import '../common_elements.dart';
 import '../elements/entities.dart';
-import '../elements/types.dart';
 import '../js_backend/runtime_types.dart'
     show
         RuntimeTypesChecks,
@@ -15,7 +14,6 @@
         RuntimeTypesSubstitutions;
 import '../options.dart';
 import '../universe/world_builder.dart';
-import '../world.dart' show ClosedWorld;
 
 class TypeTestRegistry {
   final ElementEnvironment _elementEnvironment;
@@ -26,12 +24,11 @@
 
   final CompilerOptions _options;
   final CodegenWorldBuilder _codegenWorldBuilder;
-  final ClosedWorld _closedWorld;
 
   RuntimeTypesChecks _rtiChecks;
 
-  TypeTestRegistry(this._options, this._codegenWorldBuilder, this._closedWorld,
-      this._elementEnvironment);
+  TypeTestRegistry(
+      this._options, this._codegenWorldBuilder, this._elementEnvironment);
 
   RuntimeTypesChecks get rtiChecks {
     assert(
@@ -68,46 +65,9 @@
       }
     }
 
-    // 1.  Add classes that are referenced by type arguments or substitutions in
-    //     argument checks.
+    // Add classes that are referenced by type arguments or substitutions in
+    // argument checks.
     addClassesWithSuperclasses(rtiChecks.requiredClasses);
-
-    bool canTearOff(MemberEntity function) {
-      if (!function.isFunction ||
-          function.isConstructor ||
-          function.isGetter ||
-          function.isSetter) {
-        return false;
-      } else if (function.isInstanceMember) {
-        if (!function.enclosingClass.isClosure) {
-          return _codegenWorldBuilder.hasInvokedGetter(function, _closedWorld);
-        }
-      }
-      return false;
-    }
-
-    bool canBeReflectedAsFunction(MemberEntity element) {
-      return !element.isField;
-    }
-
-    bool canBeReified(MemberEntity element) {
-      return canTearOff(element);
-    }
-
-    // 2. Find all types referenced from the types of elements that can be
-    // reflected on 'as functions'.
-    liveMembers.where((MemberEntity element) {
-      return canBeReflectedAsFunction(element) && canBeReified(element);
-    }).forEach((_function) {
-      FunctionEntity function = _function;
-      FunctionType type = _elementEnvironment.getFunctionType(function);
-      for (ClassEntity cls in _rtiChecks.getReferencedClasses(type)) {
-        while (cls != null) {
-          _rtiNeededClasses.add(cls);
-          cls = _elementEnvironment.getSuperClass(cls);
-        }
-      }
-    });
   }
 
   void computeRequiredTypeChecks(RuntimeTypesChecksBuilder rtiChecksBuilder) {
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 471f829..8675593 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -235,6 +235,7 @@
 f_bounded_quantification5_test: Fail, OK # Issue 12605
 
 [ $compiler == dart2js && $fast_startup && $fasta ]
+call_function_apply_test: RuntimeError # Issue 23873
 constructor_redirect1_negative_test: Crash # Stack Overflow
 constructor_redirect2_negative_test: Crash # Stack Overflow
 cyclic_constructor_test/01: Crash # Stack Overflow
@@ -289,7 +290,6 @@
 bit_operations_test/04: RuntimeError
 bit_operations_test/none: RuntimeError
 branch_canonicalization_test: RuntimeError
-call_function_apply_test: RuntimeError
 call_nonexistent_constructor_test/01: RuntimeError
 call_type_literal_test/01: RuntimeError
 canonical_const2_test: RuntimeError