[dart2js] Move embedded globals earlier

In anticipation of adding type metadata for --experiment-new-rti, move the embedded
globals earlier so they are available for generating constants.

The metadata for custom elements is split out since it depends on constants.

Change-Id: Ic99895bd1a1f7bf42a1f41948733ea001df8a8e2
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/106007
Reviewed-by: Mayank Patke <fishythefish@google.com>
Commit-Queue: Stephen Adams <sra@google.com>
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
index 0e58794..b33324b 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
@@ -432,12 +432,15 @@
 // Builds the inheritance structure.
 #inheritance;
 
+// Emits the embedded globals. This needs to be before constants so the embedded
+// global type resources are available for generating constants.
+#embeddedGlobalsPart1;
+
 // Instantiates all constants.
 #constants;
 
-// Emits the embedded globals. Due to type checks in eager initializers this is
-// needed before static non-final fields initializers.
-#embeddedGlobals;
+// Adds to the embedded globals. A few globals refer to constants.
+#embeddedGlobalsPart2; 
 
 // Initializes the static non-final fields (with their constant values).
 #staticNonFinalFields;
@@ -660,7 +663,10 @@
       'constants': emitConstants(fragment),
       'staticNonFinalFields': emitStaticNonFinalFields(fragment),
       'lazyStatics': emitLazilyInitializedStatics(fragment),
-      'embeddedGlobals': emitEmbeddedGlobals(program, deferredLoadingState),
+      'embeddedGlobalsPart1':
+          emitEmbeddedGlobalsPart1(program, deferredLoadingState),
+      'embeddedGlobalsPart2':
+          emitEmbeddedGlobalsPart2(program, deferredLoadingState),
       'nativeSupport': program.needsNativeSupport
           ? emitNativeSupport(fragment)
           : new js.EmptyStatement(),
@@ -1848,7 +1854,7 @@
   }
 
   /// Emits all embedded globals.
-  js.Statement emitEmbeddedGlobals(
+  js.Statement emitEmbeddedGlobalsPart1(
       Program program, DeferredLoadingState deferredLoadingState) {
     List<js.Property> globals = [];
 
@@ -1858,8 +1864,10 @@
     }
 
     if (program.typeToInterceptorMap != null) {
+      // This property is assigned later.
+      // Initialize property to avoid map transitions.
       globals.add(new js.Property(
-          js.string(TYPE_TO_INTERCEPTOR_MAP), program.typeToInterceptorMap));
+          js.string(TYPE_TO_INTERCEPTOR_MAP), js.LiteralNull()));
     }
 
     globals.add(emitMangledGlobalNames());
@@ -1887,6 +1895,17 @@
     return js.js.statement('var init = #;', globalsObject);
   }
 
+  /// Finish setting up embedded globals.
+  js.Statement emitEmbeddedGlobalsPart2(
+      Program program, DeferredLoadingState deferredLoadingState) {
+    List<js.Statement> statements = [];
+    if (program.typeToInterceptorMap != null) {
+      statements.add(js.js.statement('init.# = #;',
+          [js.string(TYPE_TO_INTERCEPTOR_MAP), program.typeToInterceptorMap]));
+    }
+    return js.Block(statements);
+  }
+
   /// Emits data needed for native classes.
   ///
   /// We don't try to reduce the size of the native data, but rather build