Be more verbose in loops etc in kernel

Benchmarks have shown that old-style for-loops are faster than for-in
for instance.

Golem says

ia32

whole stack (i.e. including utf8 and change to VariableIndexer)

AstToBinaryP90 (Intel Core i5)	6.617% (0.4 noise)
AstToBinary (Intel Xeon)	5.158% (0.4 noise)
AstToBinaryP90 (Intel Xeon)	5.104% (0.4 noise)
AstToBinaryP50 (Intel Xeon)	5.148% (0.4 noise)
AstToBinary (Intel Core i5)	6.579% (0.4 noise)
AstToBinaryP50 (Intel Core i5)	6.741% (0.4 noise)

by itself (i.e. compared to a build with utf8 and change to VariableIndexer)

AstToBinaryP90 (Intel Core i5)	0.7724% (0.0 noise)
AstToBinaryP50 (Intel Core i5)	0.7848% (0.0 noise)
AstToBinary (Intel Core i5)	0.8559% (0.0 noise)
AstToBinaryP90 (Intel Xeon)	0.7730% (0.1 noise)
AstToBinaryP50 (Intel Xeon)	0.8195% (0.1 noise)
AstToBinary (Intel Xeon)	0.9319% (0.1 noise)



x64

whole stack (i.e. including utf8 and change to VariableIndexer)

AstToBinaryP90 (Intel Core i5)	5.555% (0.2 noise)
AstToBinaryP50 (Intel Xeon)	6.352% (0.4 noise)
AstToBinaryP50 (Intel Core i5)	5.395% (0.5 noise)
AstToBinary (Intel Xeon)	6.928% (0.5 noise)
AstToBinaryP90 (Intel Xeon)	7.180% (0.5 noise)
AstToBinary (Intel Core i5)	5.824% (0.5 noise)

by itself  (i.e. compared to a build with utf8 and change to VariableIndexer)

AstToBinaryP90 (Intel Core i5)	0.1039% (0.0 noise)
AstToBinaryP50 (Intel Core i5)	0.6154% (0.0 noise)
AstToBinary (Intel Core i5)	0.7640% (0.1 noise)
AstToBinaryP50 (Intel Xeon)	1.268% (0.1 noise)
AstToBinary (Intel Xeon)	1.457% (0.1 noise)
AstToBinaryP90 (Intel Xeon)	1.512% (0.1 noise)



Change-Id: If091a3a01f2fe6574712946a01644413033739b6
Reviewed-on: https://dart-review.googlesource.com/c/85341
Commit-Queue: Jens Johansen <jensj@google.com>
Reviewed-by: Peter von der Ahé <ahe@google.com>
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 3006953..78bc419 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -383,16 +383,20 @@
 
   void computeCanonicalNames() {
     assert(canonicalName != null);
-    for (var typedef_ in typedefs) {
+    for (int i = 0; i < typedefs.length; ++i) {
+      Typedef typedef_ = typedefs[i];
       canonicalName.getChildFromTypedef(typedef_).bindTo(typedef_.reference);
     }
-    for (var field in fields) {
+    for (int i = 0; i < fields.length; ++i) {
+      Field field = fields[i];
       canonicalName.getChildFromMember(field).bindTo(field.reference);
     }
-    for (var member in procedures) {
+    for (int i = 0; i < procedures.length; ++i) {
+      Procedure member = procedures[i];
       canonicalName.getChildFromMember(member).bindTo(member.reference);
     }
-    for (var class_ in classes) {
+    for (int i = 0; i < classes.length; ++i) {
+      Class class_ = classes[i];
       canonicalName.getChild(class_.name).bindTo(class_.reference);
       class_.computeCanonicalNames();
     }
@@ -878,16 +882,20 @@
 
   void computeCanonicalNames() {
     assert(canonicalName != null);
-    for (var member in fields) {
+    for (int i = 0; i < fields.length; ++i) {
+      Field member = fields[i];
       canonicalName.getChildFromMember(member).bindTo(member.reference);
     }
-    for (var member in procedures) {
+    for (int i = 0; i < procedures.length; ++i) {
+      Procedure member = procedures[i];
       canonicalName.getChildFromMember(member).bindTo(member.reference);
     }
-    for (var member in constructors) {
+    for (int i = 0; i < constructors.length; ++i) {
+      Constructor member = constructors[i];
       canonicalName.getChildFromMember(member).bindTo(member.reference);
     }
-    for (var member in redirectingFactoryConstructors) {
+    for (int i = 0; i < redirectingFactoryConstructors.length; ++i) {
+      RedirectingFactoryConstructor member = redirectingFactoryConstructors[i];
       canonicalName.getChildFromMember(member).bindTo(member.reference);
     }
   }
@@ -5450,8 +5458,8 @@
   }
 
   void computeCanonicalNames() {
-    for (var library in libraries) {
-      computeCanonicalNamesForLibrary(library);
+    for (int i = 0; i < libraries.length; ++i) {
+      computeCanonicalNamesForLibrary(libraries[i]);
     }
   }
 
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index c4cc243..56152ba 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -493,40 +493,44 @@
   }
 
   void _checkCanonicalNameChildren(CanonicalName parent) {
-    for (CanonicalName child in parent.children) {
-      if (child.name != '@methods' &&
-          child.name != '@typedefs' &&
-          child.name != '@fields' &&
-          child.name != '@getters' &&
-          child.name != '@setters' &&
-          child.name != '@factories' &&
-          child.name != '@constructors') {
-        bool checkReferenceNode = true;
-        if (child.reference == null) {
-          // OK for "if private: URI of library" part of "Qualified name"...
-          Iterable<CanonicalName> children = child.children;
-          if (parent.parent != null &&
-              children.isNotEmpty &&
-              children.first.name.startsWith("_")) {
-            // OK then.
-            checkReferenceNode = false;
-          } else {
-            throw new CanonicalNameError(
-                "Null reference (${child.name}) ($child).");
+    Iterable<CanonicalName> parentChildren = parent.childrenOrNull;
+    if (parentChildren != null) {
+      for (CanonicalName child in parentChildren) {
+        if (child.name != '@methods' &&
+            child.name != '@typedefs' &&
+            child.name != '@fields' &&
+            child.name != '@getters' &&
+            child.name != '@setters' &&
+            child.name != '@factories' &&
+            child.name != '@constructors') {
+          bool checkReferenceNode = true;
+          if (child.reference == null) {
+            // OK for "if private: URI of library" part of "Qualified name"...
+            Iterable<CanonicalName> children = child.childrenOrNull;
+            if (parent.parent != null &&
+                children != null &&
+                children.isNotEmpty &&
+                children.first.name.startsWith("_")) {
+              // OK then.
+              checkReferenceNode = false;
+            } else {
+              throw new CanonicalNameError(
+                  "Null reference (${child.name}) ($child).");
+            }
+          }
+          if (checkReferenceNode) {
+            if (child.reference.canonicalName != child) {
+              throw new CanonicalNameError(
+                  "Canonical name and reference doesn't agree.");
+            }
+            if (child.reference.node == null) {
+              throw new CanonicalNameError(
+                  "Reference is null (${child.name}) ($child).");
+            }
           }
         }
-        if (checkReferenceNode) {
-          if (child.reference.canonicalName != child) {
-            throw new CanonicalNameError(
-                "Canonical name and reference doesn't agree.");
-          }
-          if (child.reference.node == null) {
-            throw new CanonicalNameError(
-                "Reference is null (${child.name}) ($child).");
-          }
-        }
+        _checkCanonicalNameChildren(child);
       }
-      _checkCanonicalNameChildren(child);
     }
   }
 
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index 68e8f28..cd3edbe 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -269,13 +269,15 @@
 
   void writeList<T>(List<T> items, void writeItem(T x)) {
     writeUInt30(items.length);
-    items.forEach(writeItem);
+    for (int i = 0; i < items.length; ++i) {
+      writeItem(items[i]);
+    }
   }
 
   void writeNodeList(List<Node> nodes) {
     final len = nodes.length;
     writeUInt30(len);
-    for (var i = 0; i < len; i++) {
+    for (int i = 0; i < len; i++) {
       final node = nodes[i];
       writeNode(node);
     }
@@ -313,19 +315,25 @@
 
   void indexLinkTable(Component component) {
     _canonicalNameList = <CanonicalName>[];
-    void visitCanonicalName(CanonicalName node) {
-      node.index = _canonicalNameList.length;
-      _canonicalNameList.add(node);
-      node.children.forEach(visitCanonicalName);
-    }
-
-    for (var library in component.libraries) {
+    for (int i = 0; i < component.libraries.length; ++i) {
+      Library library = component.libraries[i];
       if (!shouldWriteLibraryCanonicalNames(library)) continue;
-      visitCanonicalName(library.canonicalName);
+      _indexLinkTableInternal(library.canonicalName);
       _knownCanonicalNameNonRootTops.add(library.canonicalName);
     }
   }
 
+  void _indexLinkTableInternal(CanonicalName node) {
+    node.index = _canonicalNameList.length;
+    _canonicalNameList.add(node);
+    Iterable<CanonicalName> children = node.childrenOrNull;
+    if (children != null) {
+      for (CanonicalName child in children) {
+        _indexLinkTableInternal(child);
+      }
+    }
+  }
+
   /// Compute canonical names for the whole component or parts of it.
   void computeCanonicalNames(Component component) {
     component.computeCanonicalNames();
@@ -338,7 +346,7 @@
   bool shouldWriteLibraryCanonicalNames(Library library) => true;
 
   void writeCanonicalNameEntry(CanonicalName node) {
-    var parent = node.parent;
+    CanonicalName parent = node.parent;
     if (parent.isRoot) {
       writeUInt30(0);
     } else {
@@ -391,7 +399,7 @@
   }
 
   void _writeNodeMetadataImpl(Node node, int nodeOffset) {
-    for (var subsection in _metadataSubsections) {
+    for (_MetadataSubsection subsection in _metadataSubsections) {
       final repository = subsection.repository;
       final value = repository.mapping[node];
       if (value == null) {
@@ -473,13 +481,13 @@
 
     // RList<MetadataMapping> metadataMappings
     _binaryOffsetForMetadataMappings = getBufferOffset();
-    for (var subsection in _metadataSubsections) {
+    for (_MetadataSubsection subsection in _metadataSubsections) {
       // UInt32 tag
       writeUInt32(stringIndexer.put(subsection.repository.tag));
 
       // RList<Pair<UInt32, UInt32>> nodeOffsetToMetadataOffset
       final mappingLength = subsection.metadataMapping.length;
-      for (var i = 0; i < mappingLength; i += 2) {
+      for (int i = 0; i < mappingLength; i += 2) {
         writeUInt32(subsection.metadataMapping[i]); // node offset
         writeUInt32(subsection.metadataMapping[i + 1]); // metadata offset
       }
@@ -490,7 +498,9 @@
 
   /// Write all of some of the libraries of the [component].
   void writeLibraries(Component component) {
-    component.libraries.forEach(writeNode);
+    for (int i = 0; i < component.libraries.length; ++i) {
+      writeNode(component.libraries[i]);
+    }
   }
 
   void writeComponentIndex(Component component, List<Library> libraries) {
@@ -565,10 +575,11 @@
       List<int> lineStarts = source.lineStarts;
       writeUInt30(lineStarts.length);
       int previousLineStart = 0;
-      lineStarts.forEach((lineStart) {
+      for (int j = 0; j < lineStarts.length; ++j) {
+        int lineStart = lineStarts[j];
         writeUInt30(lineStart - previousLineStart);
         previousLineStart = lineStart;
-      });
+      }
       i++;
     }
 
@@ -674,23 +685,25 @@
     leaveScope(memberScope: true);
 
     writeNodeList(node.typedefs);
-    classOffsets = <int>[];
+    classOffsets = new List<int>();
     writeNodeList(node.classes);
     classOffsets.add(getBufferOffset());
     writeNodeList(node.fields);
-    procedureOffsets = <int>[];
+    procedureOffsets = new List<int>();
     writeNodeList(node.procedures);
     procedureOffsets.add(getBufferOffset());
 
     // Fixed-size ints at the end used as an index.
     assert(classOffsets.length > 0);
-    for (int offset in classOffsets) {
+    for (int i = 0; i < classOffsets.length; ++i) {
+      int offset = classOffsets[i];
       writeUInt32(offset);
     }
     writeUInt32(classOffsets.length - 1);
 
     assert(procedureOffsets.length > 0);
-    for (int offset in procedureOffsets) {
+    for (int i = 0; i < procedureOffsets.length; ++i) {
+      int offset = procedureOffsets[i];
       writeUInt32(offset);
     }
     writeUInt32(procedureOffsets.length - 1);
@@ -702,7 +715,7 @@
         : <LibraryDependency, int>{};
     writeUInt30(library.dependencies.length);
     for (int i = 0; i < library.dependencies.length; ++i) {
-      var importNode = library.dependencies[i];
+      LibraryDependency importNode = library.dependencies[i];
       _libraryDependencyIndex[importNode] = i;
       writeLibraryDependency(importNode);
     }
@@ -735,7 +748,7 @@
   void writeLibraryParts(Library library) {
     writeUInt30(library.parts.length);
     for (int i = 0; i < library.parts.length; ++i) {
-      var partNode = library.parts[i];
+      LibraryPart partNode = library.parts[i];
       writeLibraryPart(partNode);
     }
   }
@@ -777,7 +790,7 @@
   void writeAnnotationList(List<Expression> annotations) {
     final len = annotations.length;
     writeUInt30(len);
-    for (var i = 0; i < len; i++) {
+    for (int i = 0; i < len; i++) {
       final annotation = annotations[i];
       writeAnnotation(annotation);
     }
@@ -827,7 +840,8 @@
     leaveScope(typeParameters: node.typeParameters);
 
     assert(procedureOffsets.length > 0);
-    for (int offset in procedureOffsets) {
+    for (int i = 0; i < procedureOffsets.length; ++i) {
+      int offset = procedureOffsets[i];
       writeUInt32(offset);
     }
     writeUInt32(procedureOffsets.length - 1);
@@ -1000,9 +1014,9 @@
   void visitFunctionNode(FunctionNode node) {
     writeByte(Tag.FunctionNode);
     enterScope(typeParameters: node.typeParameters, variableScope: true);
-    var oldLabels = _labelIndexer;
+    LabelIndexer oldLabels = _labelIndexer;
     _labelIndexer = null;
-    var oldCases = _switchCaseIndexer;
+    SwitchCaseIndexer oldCases = _switchCaseIndexer;
     _switchCaseIndexer = null;
     // Note: FunctionNode has no tag.
     writeOffset(node.fileOffset);
@@ -1990,7 +2004,7 @@
   }
 
   void pushScope() {
-    scopes ??= <int>[];
+    scopes ??= new List<int>();
     scopes.add(stackHeight);
   }
 
@@ -2027,7 +2041,7 @@
   int stackHeight = 0;
 
   void enter(SwitchStatement node) {
-    for (var caseNode in node.cases) {
+    for (SwitchCase caseNode in node.cases) {
       index[caseNode] = stackHeight++;
     }
   }
@@ -2089,7 +2103,8 @@
   int stackHeight = 0;
 
   void enter(List<TypeParameter> typeParameters) {
-    for (var parameter in typeParameters) {
+    for (int i = 0; i < typeParameters.length; ++i) {
+      TypeParameter parameter = typeParameters[i];
       index[parameter] = stackHeight;
       ++stackHeight;
     }
@@ -2097,7 +2112,9 @@
 
   void exit(List<TypeParameter> typeParameters) {
     stackHeight -= typeParameters.length;
-    typeParameters.forEach(index.remove);
+    for (int i = 0; i < typeParameters.length; ++i) {
+      index.remove(typeParameters[i]);
+    }
   }
 
   int operator [](TypeParameter parameter) =>
@@ -2113,7 +2130,7 @@
   }
 
   int put(String string) {
-    var result = index[string];
+    int result = index[string];
     if (result == null) {
       result = index.length;
       index[string] = result;
@@ -2133,7 +2150,7 @@
   }
 
   int put(Uri uri) {
-    var result = index[uri];
+    int result = index[uri];
     if (result == null) {
       result = index.length;
       index[uri] = result;
@@ -2289,8 +2306,8 @@
     RangeError.checkValidIndex(index, target, null, target.length);
     end = RangeError.checkValidRange(start, end, source.length);
     if (start == end) return index;
-    var i = start;
-    var length = target.length;
+    int i = start;
+    int length = target.length;
     do {
       int codeUnit = source.codeUnitAt(i++);
       while (codeUnit < 128) {
diff --git a/pkg/kernel/lib/binary/limited_ast_to_binary.dart b/pkg/kernel/lib/binary/limited_ast_to_binary.dart
index bd00832..0b7d088 100644
--- a/pkg/kernel/lib/binary/limited_ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/limited_ast_to_binary.dart
@@ -43,10 +43,11 @@
     return predicate(library);
   }
 
-  @override
   void writeLibraries(Component component) {
-    var librariesToWrite = component.libraries.where(predicate).toList();
-    writeList(librariesToWrite, writeNode);
+    for (int i = 0; i < component.libraries.length; ++i) {
+      Library library = component.libraries[i];
+      if (predicate(library)) writeNode(library);
+    }
   }
 
   @override
diff --git a/pkg/kernel/lib/canonical_name.dart b/pkg/kernel/lib/canonical_name.dart
index 6fbc693..20bf36c 100644
--- a/pkg/kernel/lib/canonical_name.dart
+++ b/pkg/kernel/lib/canonical_name.dart
@@ -94,6 +94,8 @@
   Iterable<CanonicalName> get children =>
       _children?.values ?? const <CanonicalName>[];
 
+  Iterable<CanonicalName> get childrenOrNull => _children?.values;
+
   bool hasChild(String name) {
     return _children != null && _children.containsKey(name);
   }
@@ -175,8 +177,11 @@
 
   void unbindAll() {
     unbind();
-    for (var child in children) {
-      child.unbindAll();
+    Iterable<CanonicalName> children_ = childrenOrNull;
+    if (children_ != null) {
+      for (CanonicalName child in children_) {
+        child.unbindAll();
+      }
     }
   }