Version 2.18.0-108.0.dev

Merge commit '143c6df41b454eb0f94337f2b73862c89d5b815a' into 'dev'
diff --git a/pkg/compiler/lib/src/constants/constant_system.dart b/pkg/compiler/lib/src/constants/constant_system.dart
index cca2b93..81daa78 100644
--- a/pkg/compiler/lib/src/constants/constant_system.dart
+++ b/pkg/compiler/lib/src/constants/constant_system.dart
@@ -81,7 +81,7 @@
 
 NumConstantValue createIntFromInt(int i) => createInt(BigInt.from(i));
 
-NumConstantValue _createInt32(BigInt i) => IntConstantValue(i.toUnsigned(32));
+IntConstantValue _createInt32(BigInt i) => IntConstantValue(i.toUnsigned(32));
 
 NumConstantValue createDouble(double d) =>
     _convertToJavaScriptConstant(DoubleConstantValue(d));
@@ -98,7 +98,7 @@
   return ListConstantValue(type, values);
 }
 
-ConstantValue createType(CommonElements commonElements, DartType type) {
+TypeConstantValue createType(CommonElements commonElements, DartType type) {
   InterfaceType instanceType = commonElements.typeLiteralType;
   return TypeConstantValue(type, instanceType);
 }
@@ -112,23 +112,23 @@
 ///
 /// We consistently match that runtime semantics at compile time as well.
 bool isInt(ConstantValue constant) =>
-    constant.isInt ||
+    constant is IntConstantValue ||
     constant.isMinusZero ||
     constant.isPositiveInfinity ||
     constant.isNegativeInfinity;
 
 /// Returns true if the [constant] is a double at runtime.
 bool isDouble(ConstantValue constant) =>
-    constant.isDouble && !constant.isMinusZero;
+    constant is DoubleConstantValue && !constant.isMinusZero;
 
 /// Returns true if the [constant] is a string at runtime.
-bool isString(ConstantValue constant) => constant.isString;
+bool isString(ConstantValue constant) => constant is StringConstantValue;
 
 /// Returns true if the [constant] is a boolean at runtime.
-bool isBool(ConstantValue constant) => constant.isBool;
+bool isBool(ConstantValue constant) => constant is BoolConstantValue;
 
 /// Returns true if the [constant] is null at runtime.
-bool isNull(ConstantValue constant) => constant.isNull;
+bool isNull(ConstantValue constant) => constant is NullConstantValue;
 
 bool isSubtype(DartTypes types, DartType s, DartType t) {
   // At runtime, an integer is both an integer and a double: the
@@ -175,7 +175,8 @@
   return JavaScriptMapConstant(type, keysList, values, onlyStringKeys);
 }
 
-ConstantValue createSymbol(CommonElements commonElements, String text) {
+ConstructedConstantValue createSymbol(
+    CommonElements commonElements, String text) {
   InterfaceType type = commonElements.symbolImplementationType;
   FieldEntity field = commonElements.symbolField;
   ConstantValue argument = createString(text);
@@ -207,7 +208,7 @@
   const BitNotOperation();
 
   @override
-  ConstantValue? fold(ConstantValue constant) {
+  IntConstantValue? fold(ConstantValue constant) {
     if (isInt(constant)) {
       // In JavaScript we don't check for -0 and treat it as if it was zero.
       if (constant.isMinusZero) {
@@ -229,8 +230,8 @@
   const NegateOperation();
 
   @override
-  ConstantValue? fold(ConstantValue constant) {
-    ConstantValue? _fold(ConstantValue constant) {
+  NumConstantValue? fold(ConstantValue constant) {
+    NumConstantValue? _fold(ConstantValue constant) {
       if (constant is IntConstantValue) {
         return createInt(-constant.intValue);
       }
@@ -256,7 +257,7 @@
   const NotOperation();
 
   @override
-  ConstantValue? fold(ConstantValue constant) {
+  BoolConstantValue? fold(ConstantValue constant) {
     if (constant is BoolConstantValue) {
       return createBool(!constant.boolValue);
     }
@@ -269,7 +270,7 @@
   const BinaryBitOperation();
 
   @override
-  ConstantValue? fold(ConstantValue left, ConstantValue right) {
+  IntConstantValue? fold(ConstantValue left, ConstantValue right) {
     IntConstantValue? _fold(ConstantValue left, ConstantValue right) {
       if (left is IntConstantValue && right is IntConstantValue) {
         BigInt? resultValue = foldInts(left.intValue, right.intValue);
@@ -361,7 +362,7 @@
   const ShiftRightOperation();
 
   @override
-  ConstantValue? fold(ConstantValue left, ConstantValue right) {
+  IntConstantValue? fold(ConstantValue left, ConstantValue right) {
     // Truncate the input value to 32 bits. The web implementation of '>>' is a
     // signed shift for negative values, and an unsigned for shift for
     // non-negative values.
@@ -409,7 +410,7 @@
   const BinaryBoolOperation();
 
   @override
-  ConstantValue? fold(ConstantValue left, ConstantValue right) {
+  BoolConstantValue? fold(ConstantValue left, ConstantValue right) {
     if (left is BoolConstantValue && right is BoolConstantValue) {
       bool resultValue = foldBools(left.boolValue, right.boolValue);
       return createBool(resultValue);
@@ -450,7 +451,7 @@
   const ArithmeticNumOperation();
 
   @override
-  ConstantValue? fold(ConstantValue left, ConstantValue right) {
+  NumConstantValue? fold(ConstantValue left, ConstantValue right) {
     NumConstantValue? _fold(ConstantValue left, ConstantValue right) {
       if (left is NumConstantValue && right is NumConstantValue) {
         var foldedValue;
@@ -638,7 +639,7 @@
   const RelationalNumOperation();
 
   @override
-  ConstantValue? fold(ConstantValue left, ConstantValue right) {
+  BoolConstantValue? fold(ConstantValue left, ConstantValue right) {
     if (left is NumConstantValue && right is NumConstantValue) {
       bool foldedValue;
       if (left is IntConstantValue && right is IntConstantValue) {
@@ -727,7 +728,7 @@
   const EqualsOperation();
 
   @override
-  ConstantValue? fold(ConstantValue left, ConstantValue right) {
+  BoolConstantValue? fold(ConstantValue left, ConstantValue right) {
     // Numbers need to be treated specially because: NaN != NaN, -0.0 == 0.0,
     // and 1 == 1.0.
     if (left is IntConstantValue && right is IntConstantValue) {
@@ -740,8 +741,8 @@
       return createBool(result);
     }
 
-    if (left.isConstructedObject) {
-      if (right.isNull) {
+    if (left is ConstructedConstantValue) {
+      if (right is NullConstantValue) {
         return createBool(false);
       }
       // Unless we know that the user-defined object does not implement the
@@ -796,7 +797,7 @@
 
   @override
   ConstantValue fold(ConstantValue left, ConstantValue right) {
-    if (left.isNull) return right;
+    if (left is NullConstantValue) return right;
     return left;
   }
 
@@ -811,7 +812,7 @@
   const CodeUnitAtOperation();
 
   @override
-  ConstantValue? fold(ConstantValue left, ConstantValue right) {
+  NumConstantValue? fold(ConstantValue left, ConstantValue right) {
     if (left is StringConstantValue && right is IntConstantValue) {
       String string = left.stringValue;
       int index = right.intValue.toInt();
@@ -833,10 +834,10 @@
   const RoundOperation();
 
   @override
-  ConstantValue? fold(ConstantValue constant) {
+  NumConstantValue? fold(ConstantValue constant) {
     // Be careful to round() only values that do not throw on either the host or
     // target platform.
-    ConstantValue? tryToRound(double value) {
+    NumConstantValue? tryToRound(double value) {
       // Due to differences between browsers, only 'round' easy cases. Avoid
       // cases where nudging the value up or down changes the answer.
       // 13 digits is safely within the ~15 digit precision of doubles.
@@ -874,7 +875,7 @@
   const ToIntOperation();
 
   @override
-  ConstantValue? fold(ConstantValue constant) {
+  NumConstantValue? fold(ConstantValue constant) {
     if (constant is IntConstantValue) {
       double value = constant.doubleValue;
       // The code below is written to work for any `double`, even though
@@ -968,8 +969,6 @@
       List<ConstantValue> values, this.onlyStringKeys)
       : this.keyList = keyList,
         super(type, keyList.entries, values);
-  @override
-  bool get isMap => true;
 
   @override
   List<ConstantValue> getDependencies() {
diff --git a/pkg/compiler/lib/src/constants/values.dart b/pkg/compiler/lib/src/constants/values.dart
index f2b364a..ccabdeb 100644
--- a/pkg/compiler/lib/src/constants/values.dart
+++ b/pkg/compiler/lib/src/constants/values.dart
@@ -74,28 +74,7 @@
   /// `true` if this is a valid constant value.
   bool get isConstant => true;
 
-  // TODO(48974): Clean up all these predicate getters.
-  bool get isNull => false;
-  bool get isBool => false;
-  bool get isTrue => false;
-  bool get isFalse => false;
-  bool get isInt => false;
-  bool get isDouble => false;
-  bool get isNum => false;
-  bool get isString => false;
-  bool get isList => false;
-  bool get isSet => false;
-  bool get isMap => false;
-  bool get isConstructedObject => false;
-  bool get isFunction => false;
-
-  /// Returns true if the constant is null, a bool, a number or a string.
-  bool get isPrimitive => false;
-
   /// Returns true if the constant is a list, a map or a constructed object.
-  bool get isObject => false;
-  bool get isType => false;
-  bool get isInterceptor => false;
   bool get isDummy => false;
 
   bool get isNaN => false;
@@ -144,9 +123,6 @@
   FunctionConstantValue(this.element, this.type);
 
   @override
-  bool get isFunction => true;
-
-  @override
   bool operator ==(var other) {
     if (other is! FunctionConstantValue) return false;
     return identical(other.element, element);
@@ -186,9 +162,6 @@
   const PrimitiveConstantValue();
 
   @override
-  bool get isPrimitive => true;
-
-  @override
   bool operator ==(var other) {
     // Making this method abstract does not give us an error.
     throw UnsupportedError('PrimitiveConstant.==');
@@ -211,9 +184,6 @@
   const NullConstantValue._internal();
 
   @override
-  bool get isNull => true;
-
-  @override
   DartType getType(CommonElements types) => types.nullType;
 
   @override
@@ -239,9 +209,6 @@
 abstract class NumConstantValue extends PrimitiveConstantValue {
   double get doubleValue;
 
-  @override
-  bool get isNum => true;
-
   const NumConstantValue();
 }
 
@@ -268,9 +235,6 @@
 
   const IntConstantValue._internal(this.intValue);
 
-  @override
-  bool get isInt => true;
-
   bool isUInt31() => intValue.toUnsigned(31) == intValue;
 
   bool isUInt32() => intValue.toUnsigned(32) == intValue;
@@ -334,9 +298,6 @@
   const DoubleConstantValue._internal(this.doubleValue);
 
   @override
-  bool get isDouble => true;
-
-  @override
   bool get isNaN => doubleValue.isNaN;
 
   // We need to check for the negative sign since -0.0 == 0.0.
@@ -396,9 +357,6 @@
 
   const BoolConstantValue._internal();
 
-  @override
-  bool get isBool => true;
-
   bool get boolValue;
 
   @override
@@ -423,9 +381,6 @@
   const TrueConstantValue._internal() : super._internal();
 
   @override
-  bool get isTrue => true;
-
-  @override
   bool get boolValue => true;
 
   @override
@@ -449,9 +404,6 @@
   const FalseConstantValue._internal() : super._internal();
 
   @override
-  bool get isFalse => true;
-
-  @override
   bool get boolValue => false;
 
   @override
@@ -481,9 +433,6 @@
         this.hashCode = value.hashCode;
 
   @override
-  bool get isString => true;
-
-  @override
   DartType getType(CommonElements types) => types.stringType;
 
   @override
@@ -520,9 +469,6 @@
   ObjectConstantValue(this.type);
 
   @override
-  bool get isObject => true;
-
-  @override
   DartType getType(CommonElements types) => type;
 
   void _unparseTypeArguments(DartTypes? dartTypes, StringBuffer sb) {
@@ -541,9 +487,6 @@
   TypeConstantValue(this.representedType, InterfaceType type) : super(type);
 
   @override
-  bool get isType => true;
-
-  @override
   bool operator ==(other) {
     return other is TypeConstantValue &&
         representedType == other.representedType;
@@ -580,9 +523,6 @@
         super(type);
 
   @override
-  bool get isList => true;
-
-  @override
   bool operator ==(var other) {
     if (identical(this, other)) return true;
     if (other is! ListConstantValue) return false;
@@ -646,9 +586,6 @@
         super(type);
 
   @override
-  bool get isSet => true;
-
-  @override
   bool operator ==(var other) {
     if (identical(this, other)) return true;
     if (other is! SetConstantValue) return false;
@@ -717,9 +654,6 @@
   }
 
   @override
-  bool get isMap => true;
-
-  @override
   bool operator ==(var other) {
     if (identical(this, other)) return true;
     if (other is! MapConstantValue) return false;
@@ -795,9 +729,6 @@
   InterceptorConstantValue(this.cls);
 
   @override
-  bool get isInterceptor => true;
-
-  @override
   bool operator ==(other) {
     return other is InterceptorConstantValue && cls == other.cls;
   }
@@ -983,9 +914,6 @@
   }
 
   @override
-  bool get isConstructedObject => true;
-
-  @override
   bool operator ==(var otherVar) {
     if (identical(this, otherVar)) return true;
     if (otherVar is! ConstructedConstantValue) return false;
diff --git a/pkg/compiler/lib/src/deferred_load/deferred_load.dart b/pkg/compiler/lib/src/deferred_load/deferred_load.dart
index e3201e0..6cf76fd 100644
--- a/pkg/compiler/lib/src/deferred_load/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load/deferred_load.dart
@@ -284,7 +284,7 @@
     show Metric, Metrics, CountMetric, DurationMetric;
 import '../common/tasks.dart' show CompilerTask;
 import '../compiler.dart' show Compiler;
-import '../constants/values.dart' show ConstantValue;
+import '../constants/values.dart';
 import '../elements/types.dart';
 import '../elements/entities.dart';
 import '../kernel/element_map.dart';
@@ -586,7 +586,7 @@
         var value = d.entity;
         // Skip primitive values: they are not stored in the constant tables and
         // if they are shared, they end up duplicated anyways across output units.
-        if (value.isPrimitive) return;
+        if (value is PrimitiveConstantValue) return;
         constantMap
             .putIfAbsent(importSet.unit, () => [])
             .add(value.toStructuredText(dartTypes));
diff --git a/pkg/compiler/lib/src/inferrer/builder.dart b/pkg/compiler/lib/src/inferrer/builder.dart
index 5f0c796..f5d9729 100644
--- a/pkg/compiler/lib/src/inferrer/builder.dart
+++ b/pkg/compiler/lib/src/inferrer/builder.dart
@@ -1285,10 +1285,12 @@
       if (member.isField) {
         FieldAnalysisData fieldData =
             _closedWorld.fieldAnalysis.getFieldData(member);
-        if (fieldData.isEffectivelyConstant && fieldData.constantValue.isInt) {
-          IntConstantValue intValue = fieldData.constantValue;
-          if (intValue.intValue.isValidInt) {
-            return finish(intValue.intValue.toInt());
+        ConstantValue constantValue = fieldData.constantValue;
+        if (fieldData.isEffectivelyConstant &&
+            constantValue is IntConstantValue) {
+          BigInt intValue = constantValue.intValue;
+          if (intValue.isValidInt) {
+            return finish(intValue.toInt());
           }
         }
       }
diff --git a/pkg/compiler/lib/src/inferrer/engine.dart b/pkg/compiler/lib/src/inferrer/engine.dart
index bf20e92..65036f5 100644
--- a/pkg/compiler/lib/src/inferrer/engine.dart
+++ b/pkg/compiler/lib/src/inferrer/engine.dart
@@ -586,10 +586,8 @@
             // constant folding that could give more precise results.
             ConstantValue value = _getFieldConstant(field);
             if (value != null) {
-              if (value.isFunction) {
-                FunctionConstantValue functionConstant = value;
-                FunctionEntity function = functionConstant.element;
-                type = types.allocateClosure(function);
+              if (value is FunctionConstantValue) {
+                type = types.allocateClosure(value.element);
               } else {
                 // Although we might find a better type, we have to keep
                 // the old type around to ensure that we get a complete view
diff --git a/pkg/compiler/lib/src/inferrer/powersets/powerset_bits.dart b/pkg/compiler/lib/src/inferrer/powersets/powerset_bits.dart
index 823f59a..e99023b 100644
--- a/pkg/compiler/lib/src/inferrer/powersets/powerset_bits.dart
+++ b/pkg/compiler/lib/src/inferrer/powersets/powerset_bits.dart
@@ -193,13 +193,13 @@
   bool isPrimitiveValue(int value) => isSingleton(value);
 
   int computeAbstractValueForConstant(ConstantValue value) {
-    if (value.isTrue) {
+    if (value is TrueConstantValue) {
       return trueValue;
     }
-    if (value.isFalse) {
+    if (value is FalseConstantValue) {
       return falseValue;
     }
-    if (value.isNull) {
+    if (value is NullConstantValue) {
       return nullValue;
     }
 
diff --git a/pkg/compiler/lib/src/js_backend/codegen_listener.dart b/pkg/compiler/lib/src/js_backend/codegen_listener.dart
index 6682b3e..b63bba17 100644
--- a/pkg/compiler/lib/src/js_backend/codegen_listener.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen_listener.dart
@@ -165,24 +165,21 @@
     DartType type = constant.getType(_commonElements);
     _computeImpactForInstantiatedConstantType(type, impactBuilder);
 
-    if (constant.isFunction) {
-      FunctionConstantValue function = constant;
+    if (constant is FunctionConstantValue) {
       impactBuilder
-          .registerStaticUse(StaticUse.staticTearOff(function.element));
-    } else if (constant.isInterceptor) {
+          .registerStaticUse(StaticUse.staticTearOff(constant.element));
+    } else if (constant is InterceptorConstantValue) {
       // An interceptor constant references the class's prototype chain.
-      InterceptorConstantValue interceptor = constant;
-      ClassEntity cls = interceptor.cls;
+      ClassEntity cls = constant.cls;
       _computeImpactForInstantiatedConstantType(
           _elementEnvironment.getThisType(cls), impactBuilder);
-    } else if (constant.isType) {
+    } else if (constant is TypeConstantValue) {
       impactBuilder
           .registerTypeUse(TypeUse.instantiation(_commonElements.typeType));
       // If the type is a web component, we need to ensure the constructors are
       // available to 'upgrade' the native object.
-      TypeConstantValue type = constant;
-      if (type.representedType is InterfaceType) {
-        InterfaceType representedType = type.representedType;
+      if (constant.representedType is InterfaceType) {
+        InterfaceType representedType = constant.representedType;
         _customElementsAnalysis.registerTypeConstant(representedType.element);
       }
     } else if (constant is InstantiationConstantValue) {
diff --git a/pkg/compiler/lib/src/js_backend/constant_emitter.dart b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
index fcc9618..40c830d 100644
--- a/pkg/compiler/lib/src/js_backend/constant_emitter.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
@@ -132,7 +132,7 @@
   @override
   jsAst.Expression visitBool(BoolConstantValue constant, [_]) {
     if (_options.enableMinification) {
-      if (constant.isTrue) {
+      if (constant is TrueConstantValue) {
         // Use !0 for true.
         return js("!0");
       } else {
@@ -140,7 +140,7 @@
         return js("!1");
       }
     } else {
-      return constant.isTrue ? js('true') : js('false');
+      return constant is TrueConstantValue ? js('true') : js('false');
     }
   }
 
diff --git a/pkg/compiler/lib/src/js_backend/field_analysis.dart b/pkg/compiler/lib/src/js_backend/field_analysis.dart
index 09f6add..c35ba76 100644
--- a/pkg/compiler/lib/src/js_backend/field_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/field_analysis.dart
@@ -371,10 +371,10 @@
               assert(value != null);
               if (!memberUsage.hasWrite && canBeElided(kField)) {
                 isEffectivelyConstant = true;
-              } else if (value.isNull ||
-                  value.isInt ||
-                  value.isBool ||
-                  value.isString ||
+              } else if (value is NullConstantValue ||
+                  value is IntConstantValue ||
+                  value is BoolConstantValue ||
+                  value is StringConstantValue ||
                   value is LateSentinelConstantValue) {
                 // TODO(johnniwinther,sra): Support non-primitive constants in
                 // allocators when it does cause allocators to deoptimized
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index f49b6ce..3f90fc2 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -611,7 +611,7 @@
     // In the current implementation it doesn't make sense to give names to
     // function constants since the function-implementation itself serves as
     // constant and can be accessed directly.
-    assert(!constant.isFunction);
+    assert(constant is! FunctionConstantValue);
     jsAst.Name result = _constantNames[constant];
     if (result == null) {
       String longName = constantLongName(constant);
@@ -1707,7 +1707,7 @@
 
   @override
   void visitBool(BoolConstantValue constant, [_]) {
-    add(constant.isTrue ? 'true' : 'false');
+    add(constant is TrueConstantValue ? 'true' : 'false');
   }
 
   @override
@@ -1882,7 +1882,7 @@
 
   @override
   int visitBool(BoolConstantValue constant, [_]) {
-    return constant.isTrue ? 2 : 3;
+    return constant is TrueConstantValue ? 2 : 3;
   }
 
   @override
diff --git a/pkg/compiler/lib/src/js_backend/resolution_listener.dart b/pkg/compiler/lib/src/js_backend/resolution_listener.dart
index 12113ce..eacd078 100644
--- a/pkg/compiler/lib/src/js_backend/resolution_listener.dart
+++ b/pkg/compiler/lib/src/js_backend/resolution_listener.dart
@@ -208,16 +208,14 @@
     DartType type = constant.getType(_commonElements);
     _computeImpactForInstantiatedConstantType(type, impactBuilder);
 
-    if (constant.isFunction) {
-      FunctionConstantValue function = constant;
+    if (constant is FunctionConstantValue) {
       impactBuilder
-          .registerStaticUse(StaticUse.staticTearOff(function.element));
-    } else if (constant.isInterceptor) {
+          .registerStaticUse(StaticUse.staticTearOff(constant.element));
+    } else if (constant is InterceptorConstantValue) {
       // An interceptor constant references the class's prototype chain.
-      InterceptorConstantValue interceptor = constant;
-      InterfaceType type = _elementEnvironment.getThisType(interceptor.cls);
+      InterfaceType type = _elementEnvironment.getThisType(constant.cls);
       _computeImpactForInstantiatedConstantType(type, impactBuilder);
-    } else if (constant.isType) {
+    } else if (constant is TypeConstantValue) {
       FunctionEntity helper = _commonElements.createRuntimeType;
       impactBuilder.registerStaticUse(StaticUse.staticInvoke(
           helper, helper.parameterStructure.callStructure));
diff --git a/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
index 7361ff0..e4dbd59 100644
--- a/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
@@ -158,7 +158,7 @@
             targetArguments[count] =
                 _emitter.constantReference(NullConstantValue());
           } else {
-            if (!value.isNull) {
+            if (value is! NullConstantValue) {
               // If the value is the null constant, we should not pass it
               // down to the native method.
               indexOfLastOptionalArgumentInParameters = count;
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 ddd6c60c..48a2891 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
@@ -123,7 +123,7 @@
     for (ConstantValue constant in constants) {
       if (_emitter.isConstantInlinedOrAlreadyEmitted(constant)) continue;
 
-      if (constant.isList) outputContainsConstantList = true;
+      if (constant is ListConstantValue) outputContainsConstantList = true;
 
       OutputUnit constantUnit = _outputUnitData.outputUnitForConstant(constant);
       if (constantUnit == null) {
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 b9f1535..542f7d6 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
@@ -9,8 +9,7 @@
 import '../../common.dart';
 import '../../common/elements.dart' show JCommonElements, JElementEnvironment;
 import '../../common/names.dart' show Names, Selectors;
-import '../../constants/values.dart'
-    show ConstantValue, InterceptorConstantValue;
+import '../../constants/values.dart';
 import '../../deferred_load/output_unit.dart'
     show deferredPartFileName, OutputUnit, OutputUnitData;
 import '../../elements/entities.dart';
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
index 44f657d..0f2ad9b 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
@@ -110,9 +110,8 @@
 
   @override
   js.Expression constantReference(ConstantValue constant) {
-    if (constant.isFunction) {
-      FunctionConstantValue function = constant;
-      return staticClosureAccess(function.element);
+    if (constant is FunctionConstantValue) {
+      return staticClosureAccess(constant.element);
     }
     js.Expression expression = _constantEmitter.generate(constant);
     if (expression != null) {
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 fc83adb..8f32690 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
@@ -1571,7 +1571,7 @@
       ]);
       _dumpInfoTask.registerConstantAst(constant.value, assignment);
       assignments.add(assignment);
-      if (constant.value.isList) hasList = true;
+      if (constant.value is ListConstantValue) hasList = true;
     }
     if (hasList) {
       assignments.insert(
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
index a9db00c..f0ca9812 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
@@ -39,8 +39,7 @@
 import '../../common.dart';
 import '../../common/elements.dart' show CommonElements, JElementEnvironment;
 import '../../common/tasks.dart';
-import '../../constants/values.dart'
-    show ConstantValue, FunctionConstantValue, LateSentinelConstantValue;
+import '../../constants/values.dart';
 import '../../deferred_load/output_unit.dart' show OutputUnit;
 import '../../dump_info.dart';
 import '../../elements/entities.dart';
@@ -181,8 +180,8 @@
   }
 
   bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant) {
-    if (constant.isFunction) return true; // Already emitted.
-    if (constant.isPrimitive) return true; // Inlined.
+    if (constant is FunctionConstantValue) return true; // Already emitted.
+    if (constant is PrimitiveConstantValue) return true; // Inlined.
     if (constant.isDummy) return true; // Inlined.
     if (constant is LateSentinelConstantValue) return true; // Inlined.
     return false;
@@ -198,8 +197,10 @@
 
     // Emit constant interceptors first. Constant interceptors for primitives
     // might be used by code that builds other constants.  See Issue 18173.
-    if (a.isInterceptor != b.isInterceptor) {
-      return a.isInterceptor ? -1 : 1;
+    bool aIsInterceptor = a is InterceptorConstantValue;
+    bool bIsInterceptor = b is InterceptorConstantValue;
+    if (aIsInterceptor != bIsInterceptor) {
+      return aIsInterceptor ? -1 : 1;
     }
 
     // Sorting by the long name clusters constants with the same constructor
@@ -212,9 +213,8 @@
   }
 
   js.Expression generateConstantReference(ConstantValue value) {
-    if (value.isFunction) {
-      FunctionConstantValue functionConstant = value;
-      return _emitter.staticClosureAccess(functionConstant.element);
+    if (value is FunctionConstantValue) {
+      return _emitter.staticClosureAccess(value.element);
     }
 
     // We are only interested in the "isInlined" part, but it does not hurt to
diff --git a/pkg/compiler/lib/src/kernel/kernel_impact.dart b/pkg/compiler/lib/src/kernel/kernel_impact.dart
index 85119ca..566abea 100644
--- a/pkg/compiler/lib/src/kernel/kernel_impact.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_impact.dart
@@ -852,7 +852,7 @@
         } else if (type == commonElements.functionType) {
           reporter.reportErrorMessage(computeSourceSpanFromTreeNode(node),
               MessageKind.SWITCH_CASE_FORBIDDEN, {'type': "Function"});
-        } else if (value.isObject &&
+        } else if (value is ObjectConstantValue &&
             type != commonElements.typeLiteralType &&
             overridesEquals(type)) {
           reporter.reportErrorMessage(
diff --git a/pkg/compiler/lib/src/native/behavior.dart b/pkg/compiler/lib/src/native/behavior.dart
index 7dd67d5..20d3d53 100644
--- a/pkg/compiler/lib/src/native/behavior.dart
+++ b/pkg/compiler/lib/src/native/behavior.dart
@@ -946,19 +946,24 @@
     Iterable<ConstantValue> metadata, ClassEntity cls) {
   List<String> annotations = [];
   for (ConstantValue value in metadata) {
-    if (!value.isConstructedObject) continue;
-    ConstructedConstantValue constructedObject = value;
-    if (constructedObject.type.element != cls) continue;
+    if (value is ConstructedConstantValue) {
+      if (value.type.element != cls) continue;
 
-    Iterable<ConstantValue> fields = constructedObject.fields.values;
-    // TODO(sra): Better validation of the constant.
-    if (fields.length != 1 || !fields.single.isString) {
-      reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
-          'Annotations needs one string: ${value.toStructuredText(dartTypes)}');
+      Iterable<ConstantValue> fields = value.fields.values;
+      // TODO(sra): Better validation of the constant.
+      if (fields.length == 1) {
+        ConstantValue field = fields.single;
+        if (field is StringConstantValue) {
+          annotations.add(field.stringValue);
+          continue;
+        }
+      }
+
+      reporter.internalError(
+          CURRENT_ELEMENT_SPANNABLE,
+          'Annotations needs one string: '
+          '${value.toStructuredText(dartTypes)}');
     }
-    StringConstantValue specStringConstant = fields.single;
-    String specString = specStringConstant.stringValue;
-    annotations.add(specString);
   }
   return annotations;
 }
diff --git a/pkg/compiler/lib/src/native/resolver.dart b/pkg/compiler/lib/src/native/resolver.dart
index 051995e..dcdc80d 100644
--- a/pkg/compiler/lib/src/native/resolver.dart
+++ b/pkg/compiler/lib/src/native/resolver.dart
@@ -124,9 +124,10 @@
 /// Returns `true` if [value] is named annotation based on [annotationClass].
 bool isAnnotation(
     Spannable spannable, ConstantValue value, ClassEntity annotationClass) {
-  if (!value.isConstructedObject) return null;
-  ConstructedConstantValue constructedObject = value;
-  return constructedObject.type.element == annotationClass;
+  if (value is ConstructedConstantValue) {
+    return value.type.element == annotationClass;
+  }
+  return null;
 }
 
 /// Extracts the name if [value] is a named annotation based on
@@ -134,24 +135,25 @@
 String readAnnotationName(DartTypes dartTypes, Spannable spannable,
     ConstantValue value, ClassEntity annotationClass,
     {String defaultValue}) {
-  if (!value.isConstructedObject) return null;
-  ConstructedConstantValue constructedObject = value;
-  if (constructedObject.type.element != annotationClass) return null;
+  if (value is ConstructedConstantValue) {
+    if (value.type.element != annotationClass) return null;
 
-  Iterable<ConstantValue> fields = constructedObject.fields.values;
-  // TODO(sra): Better validation of the constant.
-  if (fields.length != 1) {
-    failedAt(spannable,
-        'Annotations needs one string: ${value.toStructuredText(dartTypes)}');
-    return null;
-  } else if (fields.single is StringConstantValue) {
-    StringConstantValue specStringConstant = fields.single;
-    return specStringConstant.stringValue;
-  } else if (defaultValue != null && fields.single is NullConstantValue) {
-    return defaultValue;
-  } else {
-    failedAt(spannable,
-        'Annotations needs one string: ${value.toStructuredText(dartTypes)}');
-    return null;
+    Iterable<ConstantValue> fields = value.fields.values;
+    // TODO(sra): Better validation of the constant.
+    if (fields.length != 1) {
+      failedAt(spannable,
+          'Annotations needs one string: ${value.toStructuredText(dartTypes)}');
+      return null;
+    } else if (fields.single is StringConstantValue) {
+      StringConstantValue specStringConstant = fields.single;
+      return specStringConstant.stringValue;
+    } else if (defaultValue != null && fields.single is NullConstantValue) {
+      return defaultValue;
+    } else {
+      failedAt(spannable,
+          'Annotations needs one string: ${value.toStructuredText(dartTypes)}');
+      return null;
+    }
   }
+  return null;
 }
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index c394f07..442efaf 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -1826,7 +1826,7 @@
 
     if (condition.isConstant()) {
       HConstant constant = condition;
-      if (constant.constant.isTrue) {
+      if (constant.constant is TrueConstantValue) {
         generateStatements(info.thenGraph);
       } else {
         generateStatements(info.elseGraph);
@@ -2491,10 +2491,10 @@
     generateConstant(node.constant, node.sourceInformation);
 
     _registry.registerConstantUse(ConstantUse.literal(node.constant));
-    if (node.constant.isType) {
-      TypeConstantValue typeConstant = node.constant;
-      _registry.registerTypeUse(
-          TypeUse.constTypeLiteral(typeConstant.representedType));
+    ConstantValue constant = node.constant;
+    if (constant is TypeConstantValue) {
+      _registry
+          .registerTypeUse(TypeUse.constTypeLiteral(constant.representedType));
     }
   }
 
diff --git a/pkg/compiler/lib/src/ssa/codegen_helpers.dart b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
index 3600c44..dfc43d5 100644
--- a/pkg/compiler/lib/src/ssa/codegen_helpers.dart
+++ b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
@@ -158,8 +158,9 @@
           // We also leave HIf nodes in place when one branch is dead.
           HInstruction condition = current.inputs.first;
           if (condition is HConstant) {
-            bool isTrue = condition.constant.isTrue;
-            successor = isTrue ? current.thenBlock : current.elseBlock;
+            successor = condition.constant is TrueConstantValue
+                ? current.thenBlock
+                : current.elseBlock;
           }
         }
         if (successor != null && successor.id > current.block.id) {
@@ -1195,17 +1196,17 @@
     if (node.usedBy.length <= 1) return;
     ConstantValue constant = node.constant;
 
-    if (constant.isNull) {
+    if (constant is NullConstantValue) {
       _handleNull(node);
       return;
     }
 
-    if (constant.isInt) {
+    if (constant is IntConstantValue) {
       _handleInt(node, constant);
       return;
     }
 
-    if (constant.isString) {
+    if (constant is StringConstantValue) {
       _handleString(node, constant);
       return;
     }
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index b03f82b..573444a 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -2946,26 +2946,27 @@
   @override
   bool isConstant() => true;
   @override
-  bool isConstantBoolean() => constant.isBool;
+  bool isConstantBoolean() => constant is BoolConstantValue;
   @override
-  bool isConstantNull() => constant.isNull;
+  bool isConstantNull() => constant is NullConstantValue;
   @override
-  bool isConstantNumber() => constant.isNum;
+  bool isConstantNumber() => constant is NumConstantValue;
   @override
-  bool isConstantInteger() => constant.isInt;
+  bool isConstantInteger() => constant is IntConstantValue;
   @override
-  bool isConstantString() => constant.isString;
+  bool isConstantString() => constant is StringConstantValue;
   @override
-  bool isConstantList() => constant.isList;
+  bool isConstantList() => constant is ListConstantValue;
   @override
-  bool isConstantMap() => constant.isMap;
+  bool isConstantMap() => constant is MapConstantValue;
   @override
-  bool isConstantFalse() => constant.isFalse;
+  bool isConstantFalse() => constant is FalseConstantValue;
   @override
-  bool isConstantTrue() => constant.isTrue;
+  bool isConstantTrue() => constant is TrueConstantValue;
 
   @override
-  bool isInterceptor(JClosedWorld closedWorld) => constant.isInterceptor;
+  bool isInterceptor(JClosedWorld closedWorld) =>
+      constant is InterceptorConstantValue;
 
   // Maybe avoid this if the literal is big?
   @override
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index a0ab430..95b6cb9 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -460,7 +460,7 @@
         node.isLateSentinel(_abstractValueDomain).isDefinitelyFalse) {
       ConstantValue value =
           _abstractValueDomain.getPrimitiveValue(node.instructionType);
-      if (value.isBool) {
+      if (value is BoolConstantValue) {
         return value;
       }
       // TODO(het): consider supporting other values (short strings?)
@@ -562,9 +562,8 @@
     assert(inputs.length == 1);
     HInstruction input = inputs[0];
     if (input is HConstant) {
-      HConstant constant = input;
-      bool isTrue = constant.constant.isTrue;
-      return _graph.addConstantBool(!isTrue, _closedWorld);
+      return _graph.addConstantBool(
+          input.constant is! TrueConstantValue, _closedWorld);
     } else if (input is HNot) {
       return input.inputs[0];
     }
@@ -1059,7 +1058,7 @@
     }
     if (index.isConstant()) {
       HConstant constantInstruction = index;
-      assert(!constantInstruction.constant.isInt);
+      assert(constantInstruction.constant is! IntConstantValue);
       if (!constant_system.isInt(constantInstruction.constant)) {
         // -0.0 is a double but will pass the runtime integer check.
         node.staticChecks = HBoundsCheck.ALWAYS_FALSE;
@@ -1146,7 +1145,7 @@
     }
 
     HInstruction compareConstant(HConstant constant, HInstruction input) {
-      if (constant.constant.isTrue) {
+      if (constant.constant is TrueConstantValue) {
         return input;
       } else {
         return HNot(input, _abstractValueDomain.boolType);
@@ -1428,10 +1427,8 @@
     // field.
     if (receiver is HConstant) {
       ConstantValue constant = receiver.constant;
-      if (constant.isConstructedObject) {
-        ConstructedConstantValue constructedConstant = constant;
-        Map<FieldEntity, ConstantValue> fields = constructedConstant.fields;
-        ConstantValue value = fields[node.element];
+      if (constant is ConstructedConstantValue) {
+        ConstantValue value = constant.fields[node.element];
         if (value != null) {
           return _graph.addConstant(value, _closedWorld);
         }
@@ -1735,7 +1732,7 @@
         HInstruction firstArgument = node.inputs[0];
         if (firstArgument is HConstant) {
           HConstant constant = firstArgument;
-          if (constant.constant.isTrue) return constant;
+          if (constant.constant is TrueConstantValue) return constant;
         }
       }
     } else if (commonElements.isCheckInt(element)) {
@@ -1765,8 +1762,8 @@
         HInstruction argument = node.inputs[0];
         if (argument is HConstant) {
           ConstantValue constant = argument.constant;
-          if (constant.isBool) {
-            bool value = constant.isTrue;
+          if (constant is BoolConstantValue) {
+            bool value = constant is TrueConstantValue;
             if (element == commonElements.assertTest) {
               // `assertTest(argument)` effectively negates the argument.
               return _graph.addConstantBool(!value, _closedWorld);
@@ -1882,8 +1879,7 @@
     HInstruction tryConstant() {
       if (!input.isConstant()) return null;
       HConstant constant = input;
-      if (!constant.constant.isPrimitive) return null;
-      PrimitiveConstantValue value = constant.constant;
+      ConstantValue value = constant.constant;
       if (value is IntConstantValue) {
         // Only constant-fold int.toString() when Dart and JS results the same.
         // TODO(18103): We should be able to remove this work-around when issue
@@ -2477,8 +2473,9 @@
           // We also leave HIf nodes in place when one branch is dead.
           HInstruction condition = current.inputs.first;
           if (condition is HConstant) {
-            bool isTrue = condition.constant.isTrue;
-            successor = isTrue ? current.thenBlock : current.elseBlock;
+            successor = condition.constant is TrueConstantValue
+                ? current.thenBlock
+                : current.elseBlock;
             assert(!analyzer.isDeadBlock(successor));
           }
         }
diff --git a/pkg/compiler/lib/src/ssa/value_range_analyzer.dart b/pkg/compiler/lib/src/ssa/value_range_analyzer.dart
index ffdb466..d947b06 100644
--- a/pkg/compiler/lib/src/ssa/value_range_analyzer.dart
+++ b/pkg/compiler/lib/src/ssa/value_range_analyzer.dart
@@ -127,55 +127,71 @@
   const IntValue(this.value, info) : super(info);
 
   @override
-  Value operator +(dynamic other) {
+  Value operator +(Value other) {
     if (other.isZero) return this;
-    if (other is! IntValue) return other + this;
-    dynamic constant = constant_system.add.fold(
-        constant_system.createInt(value),
-        constant_system.createInt(other.value));
-    if (!constant.isInt) return const UnknownValue();
-    return info.newIntValue(constant.intValue);
+    if (other is IntValue) {
+      ConstantValue constant = constant_system.add.fold(
+          constant_system.createInt(value),
+          constant_system.createInt(other.value));
+      if (constant is IntConstantValue) {
+        return info.newIntValue(constant.intValue);
+      }
+      return const UnknownValue();
+    }
+    return other + this;
   }
 
   @override
-  Value operator -(dynamic other) {
+  Value operator -(Value other) {
     if (other.isZero) return this;
-    if (other is! IntValue) return -other + this;
-    dynamic constant = constant_system.subtract.fold(
-        constant_system.createInt(value),
-        constant_system.createInt(other.value));
-    if (!constant.isInt) return const UnknownValue();
-    return info.newIntValue(constant.intValue);
+    if (other is IntValue) {
+      ConstantValue constant = constant_system.subtract.fold(
+          constant_system.createInt(value),
+          constant_system.createInt(other.value));
+      if (constant is IntConstantValue) {
+        return info.newIntValue(constant.intValue);
+      }
+      return const UnknownValue();
+    }
+    return -other + this;
   }
 
   @override
   Value operator -() {
     if (isZero) return this;
-    dynamic constant =
+    ConstantValue constant =
         constant_system.negate.fold(constant_system.createInt(value));
-    if (!constant.isInt) return const UnknownValue();
-    return info.newIntValue(constant.intValue);
+    if (constant is IntConstantValue) {
+      return info.newIntValue(constant.intValue);
+    }
+    return const UnknownValue();
   }
 
   @override
-  Value operator &(dynamic other) {
-    if (other is! IntValue) return const UnknownValue();
-    dynamic constant = constant_system.bitAnd.fold(
-        constant_system.createInt(value),
-        constant_system.createInt(other.value));
-    return info.newIntValue(constant.intValue);
+  Value operator &(Value other) {
+    if (other is IntValue) {
+      IntConstantValue constant = constant_system.bitAnd.fold(
+          constant_system.createInt(value),
+          constant_system.createInt(other.value));
+      return info.newIntValue(constant.intValue);
+    }
+    return const UnknownValue();
   }
 
   @override
-  Value min(dynamic other) {
-    if (other is! IntValue) return other.min(this);
-    return this.value < other.value ? this : other;
+  Value min(Value other) {
+    if (other is IntValue) {
+      return this.value < other.value ? this : other;
+    }
+    return other.min(this);
   }
 
   @override
-  Value max(dynamic other) {
-    if (other is! IntValue) return other.max(this);
-    return this.value < other.value ? other : this;
+  Value max(Value other) {
+    if (other is IntValue) {
+      return this.value < other.value ? other : this;
+    }
+    return other.max(this);
   }
 
   @override
@@ -1082,67 +1098,69 @@
 
   @override
   Range visitConditionalBranch(HConditionalBranch branch) {
-    dynamic condition = branch.condition;
+    HInstruction condition = branch.condition;
     // TODO(ngeoffray): Handle complex conditions.
-    if (condition is! HRelational) return info.newUnboundRange();
-    if (condition is HIdentity) return info.newUnboundRange();
-    HInstruction right = condition.right;
-    HInstruction left = condition.left;
-    if (left.isInteger(closedWorld.abstractValueDomain).isPotentiallyFalse) {
+    if (condition is HRelational) {
+      if (condition is HIdentity) return info.newUnboundRange();
+      HInstruction right = condition.right;
+      HInstruction left = condition.left;
+      if (left.isInteger(closedWorld.abstractValueDomain).isPotentiallyFalse) {
+        return info.newUnboundRange();
+      }
+      if (right.isInteger(closedWorld.abstractValueDomain).isPotentiallyFalse) {
+        return info.newUnboundRange();
+      }
+
+      Range rightRange = ranges[right];
+      Range leftRange = ranges[left];
+      constant_system.Operation operation = condition.operation();
+      constant_system.Operation mirrorOp = flipOperation(operation);
+      // Only update the true branch if this block is the only
+      // predecessor.
+      if (branch.trueBranch.predecessors.length == 1) {
+        assert(branch.trueBranch.predecessors[0] == branch.block);
+        // Update the true branch to use narrower ranges for [left] and
+        // [right].
+        Range range = computeConstrainedRange(operation, leftRange, rightRange);
+        if (leftRange != range) {
+          HInstruction instruction =
+              createRangeConversion(branch.trueBranch.first, left);
+          ranges[instruction] = range;
+        }
+
+        range = computeConstrainedRange(mirrorOp, rightRange, leftRange);
+        if (rightRange != range) {
+          HInstruction instruction =
+              createRangeConversion(branch.trueBranch.first, right);
+          ranges[instruction] = range;
+        }
+      }
+
+      // Only update the false branch if this block is the only
+      // predecessor.
+      if (branch.falseBranch.predecessors.length == 1) {
+        assert(branch.falseBranch.predecessors[0] == branch.block);
+        constant_system.Operation reverse = negateOperation(operation);
+        constant_system.Operation reversedMirror = flipOperation(reverse);
+        // Update the false branch to use narrower ranges for [left] and
+        // [right].
+        Range range = computeConstrainedRange(reverse, leftRange, rightRange);
+        if (leftRange != range) {
+          HInstruction instruction =
+              createRangeConversion(branch.falseBranch.first, left);
+          ranges[instruction] = range;
+        }
+
+        range = computeConstrainedRange(reversedMirror, rightRange, leftRange);
+        if (rightRange != range) {
+          HInstruction instruction =
+              createRangeConversion(branch.falseBranch.first, right);
+          ranges[instruction] = range;
+        }
+      }
+
       return info.newUnboundRange();
     }
-    if (right.isInteger(closedWorld.abstractValueDomain).isPotentiallyFalse) {
-      return info.newUnboundRange();
-    }
-
-    Range rightRange = ranges[right];
-    Range leftRange = ranges[left];
-    constant_system.Operation operation = condition.operation();
-    constant_system.Operation mirrorOp = flipOperation(operation);
-    // Only update the true branch if this block is the only
-    // predecessor.
-    if (branch.trueBranch.predecessors.length == 1) {
-      assert(branch.trueBranch.predecessors[0] == branch.block);
-      // Update the true branch to use narrower ranges for [left] and
-      // [right].
-      Range range = computeConstrainedRange(operation, leftRange, rightRange);
-      if (leftRange != range) {
-        HInstruction instruction =
-            createRangeConversion(branch.trueBranch.first, left);
-        ranges[instruction] = range;
-      }
-
-      range = computeConstrainedRange(mirrorOp, rightRange, leftRange);
-      if (rightRange != range) {
-        HInstruction instruction =
-            createRangeConversion(branch.trueBranch.first, right);
-        ranges[instruction] = range;
-      }
-    }
-
-    // Only update the false branch if this block is the only
-    // predecessor.
-    if (branch.falseBranch.predecessors.length == 1) {
-      assert(branch.falseBranch.predecessors[0] == branch.block);
-      constant_system.Operation reverse = negateOperation(operation);
-      constant_system.Operation reversedMirror = flipOperation(reverse);
-      // Update the false branch to use narrower ranges for [left] and
-      // [right].
-      Range range = computeConstrainedRange(reverse, leftRange, rightRange);
-      if (leftRange != range) {
-        HInstruction instruction =
-            createRangeConversion(branch.falseBranch.first, left);
-        ranges[instruction] = range;
-      }
-
-      range = computeConstrainedRange(reversedMirror, rightRange, leftRange);
-      if (rightRange != range) {
-        HInstruction instruction =
-            createRangeConversion(branch.falseBranch.first, right);
-        ranges[instruction] = range;
-      }
-    }
-
     return info.newUnboundRange();
   }
 
diff --git a/pkg/compiler/test/analyses/dart2js_allowed.json b/pkg/compiler/test/analyses/dart2js_allowed.json
index 4d58ce5..2d86d0b 100644
--- a/pkg/compiler/test/analyses/dart2js_allowed.json
+++ b/pkg/compiler/test/analyses/dart2js_allowed.json
@@ -56,13 +56,6 @@
   "pkg/compiler/lib/src/serialization/binary_sink.dart": {
     "Dynamic access of 'index'.": 1
   },
-  "pkg/compiler/lib/src/ssa/value_range_analyzer.dart": {
-    "Dynamic access of 'isZero'.": 2,
-    "Dynamic invocation of '+'.": 2,
-    "Dynamic invocation of 'max'.": 1,
-    "Dynamic invocation of 'min'.": 1,
-    "Dynamic invocation of 'unary-'.": 1
-  },
   "pkg/compiler/lib/src/util/enumset.dart": {
     "Dynamic access of 'index'.": 4
   },
diff --git a/pkg/compiler/test/deferred/follow_constant_dependencies_test.dart b/pkg/compiler/test/deferred/follow_constant_dependencies_test.dart
index b277092..3b05b87 100644
--- a/pkg/compiler/test/deferred/follow_constant_dependencies_test.dart
+++ b/pkg/compiler/test/deferred/follow_constant_dependencies_test.dart
@@ -37,7 +37,8 @@
     for (String stringValue in ["cA", "cB", "cC"]) {
       StringConstantValue constant =
           allConstants.firstWhere((dynamic constant) {
-        return constant.isString && constant.stringValue == stringValue;
+        return constant is StringConstantValue &&
+            constant.stringValue == stringValue;
       });
       Expect.notEquals(
           null,
diff --git a/pkg/compiler/test/deferred_loading/deferred_loading_test_helper.dart b/pkg/compiler/test/deferred_loading/deferred_loading_test_helper.dart
index fe2a251..b576e42 100644
--- a/pkg/compiler/test/deferred_loading/deferred_loading_test_helper.dart
+++ b/pkg/compiler/test/deferred_loading/deferred_loading_test_helper.dart
@@ -289,7 +289,7 @@
     if (node is ir.Field && node.isConst) {
       ir.Expression initializer = node.initializer;
       ConstantValue constant = _elementMap.getConstantValue(node, initializer);
-      if (!constant.isPrimitive) {
+      if (constant is! PrimitiveConstantValue) {
         SourceSpan span = computeSourceSpanFromTreeNode(initializer);
         if (initializer is ir.ConstructorInvocation) {
           // Adjust the source-span to match the AST-based location. The kernel FE
@@ -321,7 +321,7 @@
   @override
   visitConstantExpression(ir.ConstantExpression node) {
     ConstantValue constant = _elementMap.getConstantValue(null, node);
-    if (!constant.isPrimitive) {
+    if (constant is! PrimitiveConstantValue) {
       _constants.add('${constant.toStructuredText(_elementMap.types)}='
           '${outputUnitString(_data.outputUnitForConstant(constant))}');
     }
diff --git a/pkg/dev_compiler/lib/src/kernel/target.dart b/pkg/dev_compiler/lib/src/kernel/target.dart
index 2fb1100..bce2385 100644
--- a/pkg/dev_compiler/lib/src/kernel/target.dart
+++ b/pkg/dev_compiler/lib/src/kernel/target.dart
@@ -133,7 +133,9 @@
   @override
   bool allowPlatformPrivateLibraryAccess(Uri importer, Uri imported) =>
       super.allowPlatformPrivateLibraryAccess(importer, imported) ||
-      _allowedTestLibrary(importer);
+      _allowedTestLibrary(importer) ||
+      (importer.isScheme('package') &&
+          importer.path.startsWith('dart2js_runtime_metrics/'));
 
   @override
   bool get nativeExtensionExpectsString => false;
diff --git a/sdk/lib/_internal/js_dev_runtime/private/runtime_metrics.dart b/sdk/lib/_internal/js_dev_runtime/private/runtime_metrics.dart
new file mode 100644
index 0000000..c4a79a0
--- /dev/null
+++ b/sdk/lib/_internal/js_dev_runtime/private/runtime_metrics.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2022, 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.
+
+// This file is a stub to allow dart:_dart2js_runtime_metrics to be discovered
+// across web contexts.
+
+get runtimeMetrics => throw UnimplementedError();
+
+get startupMetrics => throw UnimplementedError();
diff --git a/sdk/lib/libraries.json b/sdk/lib/libraries.json
index 6c26f22..b72ab82 100644
--- a/sdk/lib/libraries.json
+++ b/sdk/lib/libraries.json
@@ -433,6 +433,9 @@
       "_native_typed_data": {
         "uri": "_internal/js_dev_runtime/private/native_typed_data.dart"
       },
+      "_dart2js_runtime_metrics": {
+        "uri": "_internal/js_dev_runtime/private/runtime_metrics.dart"
+      },
       "async": {
         "uri": "async/async.dart",
         "patches": "_internal/js_dev_runtime/patch/async_patch.dart"
diff --git a/sdk/lib/libraries.yaml b/sdk/lib/libraries.yaml
index 2b05632..92231cb 100644
--- a/sdk/lib/libraries.yaml
+++ b/sdk/lib/libraries.yaml
@@ -399,6 +399,9 @@
       _native_typed_data:
         uri: "_internal/js_dev_runtime/private/native_typed_data.dart"
 
+      _dart2js_runtime_metrics:
+        uri: "_internal/js_dev_runtime/private/runtime_metrics.dart"
+
       async:
         uri: "async/async.dart"
         patches: "_internal/js_dev_runtime/patch/async_patch.dart"
diff --git a/tools/VERSION b/tools/VERSION
index 05f1cda..bae5fe4 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 18
 PATCH 0
-PRERELEASE 107
+PRERELEASE 108
 PRERELEASE_PATCH 0
\ No newline at end of file