[VM compiler] Take FutureOr into account when checking for Number type.

A field typed 'FutureOr<T>' may contain an instance of a Number type at runtime.
This fixes issue #35542 and adds a regression test.

Change-Id: Idd19dff3edc5e061da28ab2906c34b3133ea8bd8
Reviewed-on: https://dart-review.googlesource.com/c/88280
Commit-Queue: Régis Crelier <regis@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 82f52f3e..65d80af 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -3058,12 +3058,22 @@
   return (cid == kDynamicCid) || (cid == kMintCid) || (cid == kDoubleCid);
 }
 
-static bool MaybeNumber(CompileType* type) {
+static bool MayBeNumber(CompileType* type) {
+  if (type->IsNone()) {
+    return false;
+  }
+  auto& compile_type = AbstractType::Handle(type->ToAbstractType()->raw());
+  if (compile_type.IsType() &&
+      Class::Handle(compile_type.type_class()).IsFutureOrClass()) {
+    const auto& type_args = TypeArguments::Handle(compile_type.arguments());
+    if (type_args.IsNull()) {
+      return true;
+    }
+    compile_type = type_args.TypeAt(0);
+  }
   // Note that type 'Number' is a subtype of itself.
-  return type->ToAbstractType()->IsDynamicType() ||
-         type->ToAbstractType()->IsObjectType() ||
-         type->ToAbstractType()->IsTypeParameter() ||
-         type->IsSubtypeOf(Type::Handle(Type::Number()));
+  return compile_type.IsTopType() || compile_type.IsTypeParameter() ||
+         compile_type.IsSubtypeOf(Type::Handle(Type::Number()), Heap::kOld);
 }
 
 // Returns a replacement for a strict comparison and signals if the result has
@@ -3078,8 +3088,8 @@
     if (!MayBeBoxableNumber(compare->left()->Type()->ToCid()) ||
         !MayBeBoxableNumber(compare->right()->Type()->ToCid())) {
       compare->set_needs_number_check(false);
-    } else if (!MaybeNumber(compare->left()->Type()) ||
-               !MaybeNumber(compare->right()->Type())) {
+    } else if (!MayBeNumber(compare->left()->Type()) ||
+               !MayBeNumber(compare->right()->Type())) {
       compare->set_needs_number_check(false);
     }
   }
diff --git a/tests/language_2/regress_35542_test.dart b/tests/language_2/regress_35542_test.dart
new file mode 100644
index 0000000..9b4a217
--- /dev/null
+++ b/tests/language_2/regress_35542_test.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'package:expect/expect.dart';
+
+FutureOr<dynamic> x = 'abc';
+dynamic y = 'abc';
+
+void smi() {
+  x = 42;
+  y = 42;
+}
+
+void mint() {
+  x = 0x7fffffff00000000;
+  y = 0x7fffffff00000000;
+}
+
+void dbl() {
+  x = 1.0;
+  y = 1.0;
+}
+
+void main() {
+  smi();
+  Expect.isTrue(identical(x, y));
+  mint();
+  Expect.isTrue(identical(x, y));
+  dbl();
+  Expect.isTrue(identical(x, y));
+}