[dart2js] Convert IsTestSpecialization to sealed class hierarchy.

Change-Id: I08552d4dda928259be56e0b99f9f002baeb4d6b2
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/371240
Commit-Queue: Mayank Patke <fishythefish@google.com>
Reviewed-by: Nate Biggs <natebiggs@google.com>
Reviewed-by: Stephen Adams <sra@google.com>
diff --git a/pkg/compiler/lib/src/js_backend/specialized_checks.dart b/pkg/compiler/lib/src/js_backend/specialized_checks.dart
index aac59f5..c16d94e 100644
--- a/pkg/compiler/lib/src/js_backend/specialized_checks.dart
+++ b/pkg/compiler/lib/src/js_backend/specialized_checks.dart
@@ -10,7 +10,9 @@
 import '../js_model/js_world.dart' show JClosedWorld;
 import '../universe/class_hierarchy.dart' show ClassHierarchy;
 
-enum IsTestSpecializationKind {
+sealed class IsTestSpecialization {}
+
+enum SimpleIsTestSpecialization implements IsTestSpecialization {
   isNull,
   isNotNull,
   isString,
@@ -18,36 +20,12 @@
   isNum,
   isInt,
   isArrayTop,
-  isInstanceof,
 }
 
-class IsTestSpecialization {
-  static const isNull = IsTestSpecialization._(IsTestSpecializationKind.isNull);
-  static const isNotNull =
-      IsTestSpecialization._(IsTestSpecializationKind.isNotNull);
-  static const isString =
-      IsTestSpecialization._(IsTestSpecializationKind.isString);
-  static const isBool = IsTestSpecialization._(IsTestSpecializationKind.isBool);
-  static const isNum = IsTestSpecialization._(IsTestSpecializationKind.isNum);
-  static const isInt = IsTestSpecialization._(IsTestSpecializationKind.isInt);
-  static const isArrayTop =
-      IsTestSpecialization._(IsTestSpecializationKind.isArrayTop);
+class InstanceOfIsTestSpecialization implements IsTestSpecialization {
+  final InterfaceType interfaceType;
 
-  final IsTestSpecializationKind kind;
-  final InterfaceType? _type;
-
-  const IsTestSpecialization._(this.kind) : _type = null;
-
-  const IsTestSpecialization._instanceof(InterfaceType type)
-      : kind = IsTestSpecializationKind.isInstanceof,
-        _type = type;
-
-  bool get isInstanceof => kind == IsTestSpecializationKind.isInstanceof;
-
-  InterfaceType get interfaceType {
-    assert(kind == IsTestSpecializationKind.isInstanceof);
-    return _type!;
-  }
+  const InstanceOfIsTestSpecialization(this.interfaceType);
 }
 
 class SpecializedChecks {
@@ -56,7 +34,7 @@
     if (dartType is LegacyType) {
       DartType base = dartType.baseType;
       // `Never*` accepts only `null`.
-      if (base is NeverType) return IsTestSpecialization.isNull;
+      if (base is NeverType) return SimpleIsTestSpecialization.isNull;
       // `Object*` is top and should be handled by constant folding.
       if (base.isObject) return null;
       return _findIsTestSpecialization(base, compiland, closedWorld);
@@ -72,23 +50,23 @@
 
       if (element == commonElements.nullClass ||
           element == commonElements.jsNullClass) {
-        return IsTestSpecialization.isNull;
+        return SimpleIsTestSpecialization.isNull;
       }
 
       if (element == commonElements.jsStringClass ||
           element == commonElements.stringClass) {
-        return IsTestSpecialization.isString;
+        return SimpleIsTestSpecialization.isString;
       }
 
       if (element == commonElements.jsBoolClass ||
           element == commonElements.boolClass) {
-        return IsTestSpecialization.isBool;
+        return SimpleIsTestSpecialization.isBool;
       }
 
       if (element == commonElements.doubleClass ||
           element == commonElements.jsNumberClass ||
           element == commonElements.numClass) {
-        return IsTestSpecialization.isNum;
+        return SimpleIsTestSpecialization.isNum;
       }
 
       if (element == commonElements.jsIntClass ||
@@ -96,7 +74,7 @@
           element == commonElements.jsUInt32Class ||
           element == commonElements.jsUInt31Class ||
           element == commonElements.jsPositiveIntClass) {
-        return IsTestSpecialization.isInt;
+        return SimpleIsTestSpecialization.isInt;
       }
 
       DartTypes dartTypes = closedWorld.dartTypes;
@@ -112,12 +90,12 @@
       }
 
       if (element == commonElements.jsArrayClass) {
-        return IsTestSpecialization.isArrayTop;
+        return SimpleIsTestSpecialization.isArrayTop;
       }
 
       if (dartType.isObject) {
         assert(!dartTypes.isTopType(dartType)); // Checked above.
-        return IsTestSpecialization.isNotNull;
+        return SimpleIsTestSpecialization.isNotNull;
       }
 
       ClassHierarchy classHierarchy = closedWorld.classHierarchy;
@@ -135,7 +113,7 @@
           outputUnitData.hasOnlyNonDeferredImportPathsToClass(
               compiland, topmost)) {
         assert(!dartType.isObject); // Checked above.
-        return IsTestSpecialization._instanceof(
+        return InstanceOfIsTestSpecialization(
             elementEnvironment.getClassInstantiationToBounds(topmost));
       }
 
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index 89cc75f..44377e6 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -28,7 +28,7 @@
 import '../js_backend/runtime_types_codegen.dart';
 import '../js_backend/runtime_types_new.dart'
     show RecipeEncoder, RecipeEncoding, indexTypeVariable;
-import '../js_backend/specialized_checks.dart' show IsTestSpecializationKind;
+import '../js_backend/specialized_checks.dart';
 import '../js_backend/type_reference.dart' show TypeReference;
 import '../js_emitter/js_emitter.dart' show ModularEmitter;
 import '../js_model/elements.dart' show JGeneratorBody;
@@ -3201,34 +3201,33 @@
     }
 
     late js.Expression test;
-    switch (node.specialization.kind) {
-      case IsTestSpecializationKind.isNull:
-      case IsTestSpecializationKind.isNotNull:
+    switch (node.specialization) {
+      case SimpleIsTestSpecialization.isNull:
+      case SimpleIsTestSpecialization.isNotNull:
         // These cases should be lowered using [HIdentity] during optimization.
         failedAt(node, 'Missing lowering');
 
-      case IsTestSpecializationKind.isString:
+      case SimpleIsTestSpecialization.isString:
         test = typeof("string");
         break;
 
-      case IsTestSpecializationKind.isBool:
+      case SimpleIsTestSpecialization.isBool:
         test = isTest(_commonElements.specializedIsBool);
         break;
 
-      case IsTestSpecializationKind.isNum:
+      case SimpleIsTestSpecialization.isNum:
         test = typeof("number");
         break;
 
-      case IsTestSpecializationKind.isInt:
+      case SimpleIsTestSpecialization.isInt:
         test = isTest(_commonElements.specializedIsInt);
         break;
 
-      case IsTestSpecializationKind.isArrayTop:
+      case SimpleIsTestSpecialization.isArrayTop:
         test = handleNegative(js.js('Array.isArray(#)', [value]));
         break;
 
-      case IsTestSpecializationKind.isInstanceof:
-        InterfaceType type = node.specialization.interfaceType;
+      case InstanceOfIsTestSpecialization(interfaceType: final type):
         _registry.registerTypeUse(TypeUse.constructorReference(type));
         test = handleNegative(js.js('# instanceof #',
             [value, _emitter.constructorAccess(type.element)]));
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index 599aa02..1f395e8 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -2259,11 +2259,11 @@
     final specialization = SpecializedChecks.findIsTestSpecialization(
         node.dartType, _graph.element, _closedWorld);
 
-    if (specialization == IsTestSpecialization.isNull ||
-        specialization == IsTestSpecialization.isNotNull) {
+    if (specialization == SimpleIsTestSpecialization.isNull ||
+        specialization == SimpleIsTestSpecialization.isNotNull) {
       HInstruction nullTest = HIdentity(node.checkedInput,
           _graph.addConstantNull(_closedWorld), _abstractValueDomain.boolType);
-      if (specialization == IsTestSpecialization.isNull) return nullTest;
+      if (specialization == SimpleIsTestSpecialization.isNull) return nullTest;
       nullTest.sourceInformation = node.sourceInformation;
       node.block!.addBefore(node, nullTest);
       return HNot(nullTest, _abstractValueDomain.boolType);