[dart2js/kernel] Fix poor code with nested List.generate

Cloning of InstanceInvocation kernel ast nodes was dropping the
isInvariant and isBoundSafe flags, causing the nested List.generate
expansion to not be as well optimized. `-O3` and `-O4` were 'hiding'
the problem by removing the checks anyway.

Change-Id: Id20f2eb4ef5396691a2dd5cbdd847e2d361a21d0
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/209442
Commit-Queue: Stephen Adams <sra@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/compiler/lib/src/ssa/ssa_tracer.dart b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
index f0fa679..d25cbd8 100644
--- a/pkg/compiler/lib/src/ssa/ssa_tracer.dart
+++ b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
@@ -370,8 +370,15 @@
     String target = "$receiver.$name";
     int offset = HInvoke.ARGUMENTS_OFFSET;
     List arguments = invoke.inputs.sublist(offset);
+    final attributes = {
+      if (invoke.isInvariant) 'Invariant',
+      if (invoke.isBoundsSafe) 'BoundSafe',
+    };
+    String attributesText = attributes.isEmpty ? '' : ' $attributes';
+
     return handleGenericInvoke(kind, target, arguments) +
-        "(${invoke.receiverType})";
+        "(${invoke.receiverType})" +
+        attributesText;
   }
 
   @override
diff --git a/pkg/compiler/test/kernel/data/list_generate_2.dart.expect b/pkg/compiler/test/kernel/data/list_generate_2.dart.expect
index b58c1b6..c87b037 100644
--- a/pkg/compiler/test/kernel/data/list_generate_2.dart.expect
+++ b/pkg/compiler/test/kernel/data/list_generate_2.dart.expect
@@ -13,7 +13,7 @@
         final _in::JSArray<core::int*> _list = _in::JSArray::allocateGrowable<core::int*>(_length);
         for (core::int i = 0; i.{core::num::<}(_length){(core::num) → core::bool}; i = i.{core::num::+}(1){(core::int) →* core::int}) {
           core::int* i = i;
-          _list.{_in::JSArray::[]=}(i, i.{core::num::+}(1){(core::num*) →* core::int*}){(core::int, core::int*) → void};
+          _list.{_in::JSArray::[]=}{Invariant,BoundsSafe}(i, i.{core::num::+}(1){(core::num*) →* core::int*}){(core::int, core::int*) → void};
         }
       } =>_list){(core::int, core::List<core::int*>*) → void};
     }
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_22.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_outline_change_22.yaml.world.1.expect
index d6a452a..e32d117 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_22.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_22.yaml.world.1.expect
@@ -304,7 +304,7 @@
     operator /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ +(generic-covariant-impl dart.core::List<dart.core::int*> other) → dart.core::List<dart.core::int*>
       return block {
         final dart.core::List<dart.core::int*> #t5 = dart.core::List::of<dart.core::int*>(this);
-        #t5.{dart.core::List::addAll}(other){(dart.core::Iterable<dart.core::int*>) → void};
+        #t5.{dart.core::List::addAll}{Invariant}(other){(dart.core::Iterable<dart.core::int*>) → void};
       } =>#t5;
     method /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ sublist(dart.core::int start, [dart.core::int? end = #C2]) → dart.core::List<dart.core::int*> {
       dart.core::int listLength = this.{dart.core::List::length}{dart.core::int};
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_22.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_outline_change_22.yaml.world.2.expect
index d6a452a..e32d117 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_22.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_22.yaml.world.2.expect
@@ -304,7 +304,7 @@
     operator /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ +(generic-covariant-impl dart.core::List<dart.core::int*> other) → dart.core::List<dart.core::int*>
       return block {
         final dart.core::List<dart.core::int*> #t5 = dart.core::List::of<dart.core::int*>(this);
-        #t5.{dart.core::List::addAll}(other){(dart.core::Iterable<dart.core::int*>) → void};
+        #t5.{dart.core::List::addAll}{Invariant}(other){(dart.core::Iterable<dart.core::int*>) → void};
       } =>#t5;
     method /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ sublist(dart.core::int start, [dart.core::int? end = #C2]) → dart.core::List<dart.core::int*> {
       dart.core::int listLength = this.{dart.core::List::length}{dart.core::int};
diff --git a/pkg/kernel/lib/clone.dart b/pkg/kernel/lib/clone.dart
index c18ffb7..c65b3a2 100644
--- a/pkg/kernel/lib/clone.dart
+++ b/pkg/kernel/lib/clone.dart
@@ -677,7 +677,8 @@
     return new InstanceInvocation.byReference(
         node.kind, clone(node.receiver), node.name, clone(node.arguments),
         functionType: visitType(node.functionType) as FunctionType,
-        interfaceTargetReference: node.interfaceTargetReference);
+        interfaceTargetReference: node.interfaceTargetReference)
+      ..flags = node.flags;
   }
 
   @override