[vm] Attach type to parameters on unchecked entry.

This is especially important for multiple entry-points in AOT mode, since without the type
information we can't inline certain intrinsics (because they would have to de-opt).

Change-Id: I62352234c95a1211ff7cdabb9cefc48990427a6f
Reviewed-on: https://dart-review.googlesource.com/c/82999
Commit-Queue: Samir Jindel <sjindel@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index 7876026..37cf267 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -995,6 +995,9 @@
     return CompileType(CompileType::kNonNullable, cid, &type);
   }
 
+  const bool is_unchecked_entry_param =
+      graph_entry->unchecked_entry() == block_;
+
   if (Isolate::Current()->can_use_strong_mode_types()) {
     LocalScope* scope = graph_entry->parsed_function().node_sequence()->scope();
     // Note: in catch-blocks we have ParameterInstr for each local variable
@@ -1014,7 +1017,9 @@
       }
       // If parameter type was checked by caller, then use Dart type annotation,
       // plus non-nullability from inferred type if known.
-      if (param->was_type_checked_by_caller()) {
+      if (param->was_type_checked_by_caller() ||
+          (is_unchecked_entry_param &&
+           !param->is_explicit_covariant_parameter())) {
         const bool is_nullable =
             (inferred_type == NULL) || inferred_type->is_nullable();
         TraceStrongModeType(this, param->type());
diff --git a/runtime/vm/compiler/frontend/scope_builder.cc b/runtime/vm/compiler/frontend/scope_builder.cc
index 9fd4e21..14f2e15 100644
--- a/runtime/vm/compiler/frontend/scope_builder.cc
+++ b/runtime/vm/compiler/frontend/scope_builder.cc
@@ -299,9 +299,10 @@
           FieldHelper field_helper(&helper_);
           field_helper.ReadUntilIncluding(FieldHelper::kFlags);
 
-          if (!field_helper.IsCovariant() &&
-              (!field_helper.IsGenericCovariantImpl() ||
-               (!attrs.has_non_this_uses && !attrs.has_tearoff_uses))) {
+          if (field_helper.IsCovariant()) {
+            result_->setter_value->set_is_explicit_covariant_parameter();
+          } else if (!field_helper.IsGenericCovariantImpl() ||
+                     (!attrs.has_non_this_uses && !attrs.has_tearoff_uses)) {
             result_->setter_value->set_type_check_mode(
                 LocalVariable::kTypeCheckedByCaller);
           }
@@ -1428,6 +1429,9 @@
   if (helper.IsFinal()) {
     variable->set_is_final();
   }
+  if (helper.IsCovariant()) {
+    variable->set_is_explicit_covariant_parameter();
+  }
   if (variable->name().raw() == Symbols::IteratorParameter().raw()) {
     variable->set_is_forced_stack();
   }
diff --git a/runtime/vm/scopes.h b/runtime/vm/scopes.h
index 952ecc7..18d447c 100644
--- a/runtime/vm/scopes.h
+++ b/runtime/vm/scopes.h
@@ -88,6 +88,7 @@
         is_invisible_(false),
         is_captured_parameter_(false),
         is_forced_stack_(false),
+        is_explicit_covariant_parameter_(false),
         type_check_mode_(kDoTypeCheck),
         index_() {
     ASSERT(type.IsZoneHandle() || type.IsReadOnlyHandle());
@@ -121,6 +122,13 @@
   bool is_forced_stack() const { return is_forced_stack_; }
   void set_is_forced_stack() { is_forced_stack_ = true; }
 
+  bool is_explicit_covariant_parameter() const {
+    return is_explicit_covariant_parameter_;
+  }
+  void set_is_explicit_covariant_parameter() {
+    is_explicit_covariant_parameter_ = true;
+  }
+
   enum TypeCheckMode {
     kDoTypeCheck,
     kSkipTypeCheck,
@@ -197,6 +205,7 @@
   bool is_invisible_;
   bool is_captured_parameter_;
   bool is_forced_stack_;
+  bool is_explicit_covariant_parameter_;
   TypeCheckMode type_check_mode_;
   VariableIndex index_;