[vm] Better List.of

List.from now calls List.of instead of the other way around.

Separate loops for system Lists, EfficientLengthIterables
and other Iterables should keep the performance of these
cases independent.

Change-Id: I26a23b10d2fb8fd2683a4f9c26257860cfdfa758
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/173860
Commit-Queue: Stephen Adams <sra@google.com>
Reviewed-by: Lasse R.H. Nielsen <lrn@google.com>
diff --git a/sdk/lib/_internal/vm/lib/array_patch.dart b/sdk/lib/_internal/vm/lib/array_patch.dart
index 51fe288..df03cf6 100644
--- a/sdk/lib/_internal/vm/lib/array_patch.dart
+++ b/sdk/lib/_internal/vm/lib/array_patch.dart
@@ -30,43 +30,60 @@
 
   @patch
   factory List.from(Iterable elements, {bool growable: true}) {
-    if (elements is EfficientLengthIterable<E>) {
-      int length = elements.length;
-      var list = growable ? new _GrowableList<E>(length) : new _List<E>(length);
-      if (length > 0) {
-        // Avoid creating iterator unless necessary.
-        int i = 0;
-        for (var element in elements) {
-          list[i++] = element;
-        }
-      }
-      return list;
-    }
     // If elements is an Iterable<E>, we won't need a type-test for each
-    // element. In the "common case" that elements is an Iterable<E>, this
-    // replaces a type-test on every element with a single type-test before
-    // starting the loop.
+    // element.
     if (elements is Iterable<E>) {
-      List<E> list = new _GrowableList<E>(0);
-      for (E e in elements) {
-        list.add(e);
-      }
-      if (growable) return list;
-      return makeListFixedLength(list);
-    } else {
-      List<E> list = new _GrowableList<E>(0);
-      for (E e in elements) {
-        list.add(e);
-      }
-      if (growable) return list;
-      return makeListFixedLength(list);
+      return List.of(elements, growable: growable);
     }
+
+    List<E> list = new _GrowableList<E>(0);
+    for (E e in elements) {
+      list.add(e);
+    }
+    if (growable) return list;
+    return makeListFixedLength(list);
   }
 
   @patch
   factory List.of(Iterable<E> elements, {bool growable: true}) {
-    // TODO(32937): Specialize to benefit from known element type.
-    return List.from(elements, growable: growable);
+    final cid = ClassID.getID(elements);
+    final isVMList = (cid == ClassID.cidArray) ||
+        (cid == ClassID.cidGrowableObjectArray) ||
+        (cid == ClassID.cidImmutableArray);
+
+    if (isVMList) {
+      final ListBase<E> elementsAsList = elements as ListBase<E>;
+      final int length = elementsAsList.length;
+      final list =
+          growable ? new _GrowableList<E>(length) : new _List<E>(length);
+      if (length > 0) {
+        for (int i = 0; i < length; i++) {
+          list[i] = elementsAsList[i];
+        }
+      }
+      return list;
+    }
+
+    if (elements is EfficientLengthIterable) {
+      final int length = elements.length;
+      final list =
+          growable ? new _GrowableList<E>(length) : new _List<E>(length);
+      if (length > 0) {
+        int i = 0;
+        for (var element in elements) {
+          list[i++] = element;
+        }
+        if (i != length) throw ConcurrentModificationError(elements);
+      }
+      return list;
+    }
+
+    final list = <E>[];
+    for (var elements in elements) {
+      list.add(elements);
+    }
+    if (growable) return list;
+    return makeListFixedLength(list);
   }
 
   @patch