Revision: 7732
Author: [email protected]
Date: Mon Mar 15 14:17:17 2010
Log: A few runAsync-related code size improvements.

1) Removes the clinit, AsyncLoader__Supers, and loading fields from generated AsyncLoaders. PRETTY mode Showcase's initial fragment drops from 500k to 480k. Probably less impressive in OBF. A tiny improvement within the split fragments, too.

2) Removes the last couple uses of JRE collections from AsyncFragmentLoader in favor of arrays.

3) Removes a missed logEventProgress Integer -> int conversion that was begun in an earlier commit.

http://gwt-code-reviews.appspot.com/159811
Review by: spoon

http://code.google.com/p/google-web-toolkit/source/detail?r=7732

Modified:
 /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/FragmentLoaderCreator.java
 /trunk/user/src/com/google/gwt/core/client/impl/AsyncFragmentLoader.java
 /trunk/user/src/com/google/gwt/core/client/prefetch/Prefetcher.java
/trunk/user/test/com/google/gwt/core/client/impl/AsyncFragmentLoaderTest.java

=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/FragmentLoaderCreator.java Tue Jul 28 21:11:02 2009 +++ /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/FragmentLoaderCreator.java Mon Mar 15 11:03:52 2010
@@ -26,7 +26,6 @@
 import com.google.gwt.dev.jdt.FindDeferredBindingSitesVisitor;

 import java.io.PrintWriter;
-import java.util.List;

 /**
* Generates code for loading an island. The pattern of generated classes is
@@ -40,12 +39,12 @@
public static final String ASYNC_FRAGMENT_LOADER = "com.google.gwt.core.client.impl.AsyncFragmentLoader";
   public static final String ASYNC_LOADER_CLASS_PREFIX = "AsyncLoader";
public static final String ASYNC_LOADER_PACKAGE = "com.google.gwt.lang.asyncloaders"; + public static final String BROWSER_LOADER = "AsyncFragmentLoader.BROWSER_LOADER";
   public static final String LOADER_METHOD_RUN_ASYNC = "runAsync";
public static final String RUN_ASYNC_CALLBACK = "com.google.gwt.core.client.RunAsyncCallback"; private static final String GWT_CLASS = FindDeferredBindingSitesVisitor.MAGIC_CLASS; private static final String PROP_RUN_ASYNC_NEVER_RUNS = "gwt.jjs.runAsyncNeverRuns";
-  private static final String UNCAUGHT_EXCEPTION_HANDLER_CLASS = GWT_CLASS
-      + ".UncaughtExceptionHandler";
+ private static final String UNCAUGHT_EXCEPTION_HANDLER_CLASS = "GWT.UncaughtExceptionHandler";

   private final StandardGeneratorContext context;
   private int entryNumber = 0;
@@ -75,7 +74,6 @@
     }

     generateLoaderFields(loaderWriter);
-    generateOnErrorMethod(loaderWriter);
     generateOnLoadMethod(loaderWriter);
     generateRunAsyncMethod(loaderWriter);
     generateRunCallbacksMethod(loaderWriter);
@@ -86,22 +84,11 @@
     context.commit(logger, loaderWriter);

     writeCallbackListClass(logger, context);
-    writeLoaderSuperclass(logger, context);

     return getLoaderQualifiedName();
   }

   private void generateLoaderFields(PrintWriter srcWriter) {
- srcWriter.println("// Whether the code for this entry point has loaded");
-    srcWriter.println("private static boolean loaded = false;");
-
- srcWriter.println("// Whether the code for this entry point is currently loading");
-    srcWriter.println("private static boolean loading = false;");
-
-    srcWriter.println("// A callback caller for this entry point");
-    srcWriter.println("private static " + getLoaderSuperclassSimpleName()
-        + " instance = new " + getLoaderSuperclassSimpleName() + "();");
-
     srcWriter.println("// Callbacks that are pending");
     srcWriter.println("private static " + getCallbackListSimpleName()
         + " callbacksHead = null;");
@@ -109,27 +96,23 @@
     srcWriter.println("// The tail of the callbacks list");
     srcWriter.println("private static " + getCallbackListSimpleName()
         + " callbacksTail = null;");
-  }
-
-  private void generateOnErrorMethod(PrintWriter srcWriter) {
-    srcWriter.println("public static void onError(Throwable e) {");
-    srcWriter.println("loading = false;");
-    srcWriter.println("runCallbackOnFailures(e);");
-    srcWriter.println("}");
+
+    srcWriter.println("// A callback caller for this entry point");
+    srcWriter.println("private static " + getLoaderSimpleName()
+        + " instance = null;");
   }

   private void generateOnLoadMethod(PrintWriter srcWriter) {
     srcWriter.println("public static void onLoad() {");
-    srcWriter.println("loaded = true;");
     srcWriter.println("instance = new " + getLoaderSimpleName() + "();");
- srcWriter.println(ASYNC_FRAGMENT_LOADER + ".BROWSER_LOADER.fragmentHasLoaded("
-        + entryNumber + ");");
-
-    srcWriter.println(ASYNC_FRAGMENT_LOADER
- + ".BROWSER_LOADER.logEventProgress(\"runCallbacks" + entryNumber + "\", \"begin\");");
+    srcWriter.println(BROWSER_LOADER + ".fragmentHasLoaded(" + entryNumber
+        + ");");
+
+    srcWriter.println(BROWSER_LOADER + ".logEventProgress(\"runCallbacks"
+        + entryNumber + "\", \"begin\");");
     srcWriter.println("instance.runCallbacks();");
-    srcWriter.println(ASYNC_FRAGMENT_LOADER
- + ".BROWSER_LOADER.logEventProgress(\"runCallbacks" + entryNumber + "\", \"end\");");
+    srcWriter.println(BROWSER_LOADER + ".logEventProgress(\"runCallbacks"
+        + entryNumber + "\", \"end\");");

     srcWriter.println("}");
   }
@@ -154,16 +137,15 @@
     srcWriter.println("  callbacksHead = newCallback;");
     srcWriter.println("}");

-    srcWriter.println("if (loaded) {");
-    srcWriter.println("instance.runCallbacks();");
-    srcWriter.println("return;");
+    srcWriter.println("if (instance != null) {");
+    srcWriter.println("  instance.runCallbacks();");
+    srcWriter.println("  return;");
     srcWriter.println("}");
-    srcWriter.println("if (!loading) {");
-    srcWriter.println("loading = true;");
- srcWriter.println("AsyncFragmentLoader.BROWSER_LOADER.inject(" + entryNumber + ","); + srcWriter.println("if (!" + BROWSER_LOADER + ".isLoading(" + entryNumber
+        + ")) {");
+ srcWriter.println(" " + BROWSER_LOADER + ".inject(" + entryNumber + ",");
     srcWriter.println("  new AsyncFragmentLoader.LoadErrorHandler() {");
     srcWriter.println("    public void loadFailed(Throwable reason) {");
-    srcWriter.println("      loading = false;");
     srcWriter.println("      runCallbackOnFailures(reason);");
     srcWriter.println("    }");
     srcWriter.println("  });");
@@ -174,8 +156,8 @@
   private void generateRunCallbackOnFailuresMethod(PrintWriter srcWriter) {
srcWriter.println("private static void runCallbackOnFailures(Throwable e) {");
     srcWriter.println("while (callbacksHead != null) {");
-    srcWriter.println("callbacksHead.callback.onFailure(e);");
-    srcWriter.println("callbacksHead = callbacksHead.next;");
+    srcWriter.println("  callbacksHead.callback.onFailure(e);");
+    srcWriter.println("  callbacksHead = callbacksHead.next;");
     srcWriter.println("}");
     srcWriter.println("callbacksTail = null;");
     srcWriter.println("}");
@@ -187,8 +169,7 @@
     srcWriter.println("while (callbacksHead != null) {");

srcWriter.println(" " + UNCAUGHT_EXCEPTION_HANDLER_CLASS + " handler = "
-        + FindDeferredBindingSitesVisitor.MAGIC_CLASS
-        + ".getUncaughtExceptionHandler();");
+        + "GWT.getUncaughtExceptionHandler();");

     srcWriter.println("  " + getCallbackListSimpleName()
         + " next = callbacksHead;");
@@ -230,14 +211,6 @@
   private String getLoaderSimpleName() {
     return ASYNC_LOADER_CLASS_PREFIX + entryNumber;
   }
-
-  private String getLoaderSuperclassQualifiedName() {
-    return ASYNC_LOADER_PACKAGE + getLoaderSuperclassSimpleName();
-  }
-
-  private String getLoaderSuperclassSimpleName() {
-    return getLoaderSimpleName() + "__Super";
-  }

   private String getPackage() {
     return ASYNC_LOADER_PACKAGE;
@@ -253,15 +226,12 @@

     printWriter.println("package " + getPackage() + ";");
     String[] imports = new String[] {
-        RUN_ASYNC_CALLBACK, List.class.getCanonicalName(),
-        ASYNC_FRAGMENT_LOADER};
+        GWT_CLASS, RUN_ASYNC_CALLBACK, ASYNC_FRAGMENT_LOADER};
     for (String imp : imports) {
       printWriter.println("import " + imp + ";");
     }

- printWriter.println("public class " + getLoaderSimpleName() + " extends "
-        + getLoaderSuperclassSimpleName() + " {");
-
+    printWriter.println("public class " + getLoaderSimpleName() + " {");
     return printWriter;
   }

@@ -281,33 +251,6 @@
     printWriter.println(getCallbackListSimpleName() + " next;");
     printWriter.println("}");

-    printWriter.close();
-    ctx.commit(logger, printWriter);
-  }
-
-  /**
- * Create a stand-in superclass of the actual loader. This is used to keep the
-   * liveness analyzer from thinking the real <code>runCallbacks()</code>
-   * method is available until <code>onLoad</code> has been called and the
- * real loader instantiated. A little work on TypeTightener could prevent the
-   * need for this class.
-   */
- private void writeLoaderSuperclass(TreeLogger logger, GeneratorContext ctx)
-      throws UnableToCompleteException {
-    PrintWriter printWriter = ctx.tryCreate(logger, getPackage(),
-        getLoaderSuperclassSimpleName());
-    if (printWriter == null) {
-      logger.log(TreeLogger.ERROR, "Could not create type: "
-          + getLoaderSuperclassQualifiedName());
-      throw new UnableToCompleteException();
-    }
-
-    printWriter.println("package " + getPackage() + ";");
-    printWriter.println("public class " + getLoaderSuperclassSimpleName()
-        + " {");
-    printWriter.println("public void runCallbacks() { }");
-    printWriter.println("}");
-
     printWriter.close();
     ctx.commit(logger, printWriter);
   }
=======================================
--- /trunk/user/src/com/google/gwt/core/client/impl/AsyncFragmentLoader.java Thu Feb 18 07:33:27 2010 +++ /trunk/user/src/com/google/gwt/core/client/impl/AsyncFragmentLoader.java Mon Mar 15 11:03:52 2010
@@ -18,10 +18,6 @@
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.JavaScriptObject;

-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
 /**
  * <p>
* Low-level support to download an extra fragment of code. This should not be
@@ -187,7 +183,8 @@
* Make a local list of the handlers to run, in case one of them calls
        * another runAsync
        */
- List<LoadErrorHandler> handlersToRun = new ArrayList<LoadErrorHandler>();
+      LoadErrorHandler[] handlersToRun = pendingDownloadErrorHandlers;
+      pendingDownloadErrorHandlers = new LoadErrorHandler[numEntries + 1];

       /*
* Call clear() here so that requestedExclusives makes all of its space
@@ -195,14 +192,6 @@
        */
       requestedExclusives.clear();

-      // add handlers for pending downloads
-      for (LoadErrorHandler handler : pendingDownloadErrorHandlers) {
-        if (handler != null) {
-          handlersToRun.add(handler);
-        }
-      }
-      pendingDownloadErrorHandlers.clear();
-
       fragmentLoading = -1;

       /*
@@ -212,10 +201,12 @@
       RuntimeException lastException = null;

       for (LoadErrorHandler handler : handlersToRun) {
-        try {
-          handler.loadFailed(reason);
-        } catch (RuntimeException e) {
-          lastException = e;
+        if (handler != null) {
+          try {
+            handler.loadFailed(reason);
+          } catch (RuntimeException e) {
+            lastException = e;
+          }
         }
       }

@@ -340,7 +331,7 @@
    * Externally provided handlers for all outstanding and queued download
    * requests.
    */
- private ArrayList<LoadErrorHandler> pendingDownloadErrorHandlers = new ArrayList<LoadErrorHandler>();
+  private LoadErrorHandler[] pendingDownloadErrorHandlers;

   /**
    * Whether prefetching is currently enabled.
@@ -373,8 +364,10 @@
     this.initialLoadSequence = initialLoadSequence;
     this.loadingStrategy = loadingStrategy;
     this.logger = logger;
-    requestedExclusives = new BoundedIntQueue(numEntries + 1);
-    isLoaded = new boolean[numEntries + 1];
+    int numEntriesPlusOne = numEntries + 1;
+    requestedExclusives = new BoundedIntQueue(numEntriesPlusOne);
+    isLoaded = new boolean[numEntriesPlusOne];
+    pendingDownloadErrorHandlers = new LoadErrorHandler[numEntriesPlusOne];
   }

   /**
@@ -382,8 +375,8 @@
    */
   public void fragmentHasLoaded(int fragment) {
     logFragmentLoaded(fragment);
-    if (fragment < pendingDownloadErrorHandlers.size()) {
-      pendingDownloadErrorHandlers.set(fragment, null);
+    if (fragment < pendingDownloadErrorHandlers.length) {
+      pendingDownloadErrorHandlers[fragment] = null;
     }

     if (isInitial(fragment)) {
@@ -410,8 +403,7 @@
    * @param splitPoint the split point whose code needs to be loaded
    */
   public void inject(int splitPoint, LoadErrorHandler loadErrorHandler) {
-    setCapacity(pendingDownloadErrorHandlers, splitPoint + 1);
-    pendingDownloadErrorHandlers.set(splitPoint, loadErrorHandler);
+    pendingDownloadErrorHandlers[splitPoint] = loadErrorHandler;
     if (!isInitial(splitPoint)) {
       requestedExclusives.add(splitPoint);
     }
@@ -421,6 +413,10 @@
   public boolean isAlreadyLoaded(int splitPoint) {
    return isLoaded[splitPoint];
   }
+
+  public boolean isLoading(int splitPoint) {
+    return pendingDownloadErrorHandlers[splitPoint] != null;
+  }

   public void leftoversFragmentHasLoaded() {
     fragmentHasLoaded(leftoversFragment());
@@ -439,12 +435,12 @@
    * whenever there is nothing else to download. Each call to this method
    * overwrites the entire prefetch queue with the newly specified one.
    */
-  public void setPrefetchQueue(Collection<? extends Integer> splitPoints) {
+  public void setPrefetchQueue(int... runAsyncSplitPoints) {
     if (prefetchQueue == null) {
       prefetchQueue = new BoundedIntQueue(numEntries);
     }
     prefetchQueue.clear();
-    for (Integer sp : splitPoints) {
+    for (int sp : runAsyncSplitPoints) {
       prefetchQueue.add(sp);
     }
     startLoadingNextFragment();
@@ -472,8 +468,8 @@
     while (requestedExclusives.size() > 0
         && isLoaded[requestedExclusives.peek()]) {
       int offset = requestedExclusives.remove();
-      if (offset < pendingDownloadErrorHandlers.size()) {
-        pendingDownloadErrorHandlers.set(offset, null);
+      if (offset < pendingDownloadErrorHandlers.length) {
+        pendingDownloadErrorHandlers[offset] = null;
       }
     }

@@ -512,12 +508,12 @@
   }

   /**
-   * Return if the the ArrayList is empty.
-   * @param list the list to check if empty
+   * Returns <code>true</code> if array contains only <code>null</code>
+   * elements.
    */
-  private boolean isEmpty(ArrayList<?> list) {
-    for (int i = 0; i < list.size(); i++) {
-      if (list.get(i) != null) {
+  private boolean isEmpty(Object[] array) {
+    for (int i = 0; i < array.length; i++) {
+      if (array[i] != null) {
         return false;
       }
     }
@@ -549,8 +545,8 @@
    * <code>fragment</code> and <code>size</code> objects are allowed to be
    * <code>null</code>.
    */
-  private void logEventProgress(String eventGroup, String type,
-      Integer fragment, Integer size) {
+ private void logEventProgress(String eventGroup, String type, int fragment,
+      int size) {
     logger.logEventProgress(eventGroup, type, fragment, size);
   }

@@ -558,17 +554,6 @@
     String logGroup = downloadGroup(fragment);
     logEventProgress(logGroup, LwmLabels.END, fragment, -1);
   }
-
-  /**
-   * Set capacity ArrayList list.
-   * @param list the list to add capacity to.
-   * @param size the new size to increase the capacity to.
-   */
-  private void setCapacity(ArrayList<?> list, int size) {
-    while (list.size() < size) {
-      list.add(null);
-    }
-  }

   private void startLoadingFragment(int fragment) {
     assert (fragmentLoading < 0);
=======================================
--- /trunk/user/src/com/google/gwt/core/client/prefetch/Prefetcher.java Wed Nov 18 11:30:09 2009 +++ /trunk/user/src/com/google/gwt/core/client/prefetch/Prefetcher.java Mon Mar 15 11:03:52 2010
@@ -18,9 +18,7 @@
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.impl.AsyncFragmentLoader;

-import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.List;

 /**
  * This class allows requesting the download of resources before they are
@@ -37,14 +35,15 @@
       return;
     }

-    List<Integer> runAsyncSplitPoints = new ArrayList<Integer>();
-
+    // No range checking in web mode means we needn't precompute the size.
+    int[] runAsyncSplitPoints = new int[0];
+    int i = 0;
     for (PrefetchableResource resource : resources) {
       if (resource instanceof RunAsyncCode) {
         RunAsyncCode resourceRunAsync = (RunAsyncCode) resource;
         int splitPoint = resourceRunAsync.getSplitPoint();
if (splitPoint >= 0) { // Skip placeholders, which have a -1 split point
-          runAsyncSplitPoints.add(splitPoint);
+          runAsyncSplitPoints[i++] = splitPoint;
         }
         continue;
       }
=======================================
--- /trunk/user/test/com/google/gwt/core/client/impl/AsyncFragmentLoaderTest.java Thu Feb 18 07:33:27 2010 +++ /trunk/user/test/com/google/gwt/core/client/impl/AsyncFragmentLoaderTest.java Mon Mar 15 11:03:52 2010
@@ -21,8 +21,6 @@

 import junit.framework.TestCase;

-import static java.util.Arrays.asList;
-
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.LinkedList;
@@ -454,7 +452,7 @@
         1, 2, 3}, reqs, progress);
     loader.startPrefetching();
     // request a prefetch of something in the initial load sequence
-    loader.setPrefetchQueue(asList(2));
+    loader.setPrefetchQueue(2);
     reqs.assertFragmentsRequested(1);
     progress.assertEvent("download1", BEGIN, 1);

@@ -468,7 +466,7 @@
     progress.assertEvent("download2", END, 2);
     progress.assertNoEvents();
     // request a prefetch of an exclusive
-    loader.setPrefetchQueue(asList(4));
+    loader.setPrefetchQueue(4);
     reqs.assertFragmentsRequested(3);
     progress.assertEvent("download3", BEGIN, 3);

@@ -487,7 +485,7 @@
     progress.assertEvent("download4", END, 4);
     progress.assertNoEvents();
     // request a prefetch, but check that an inject call takes priority
-    loader.setPrefetchQueue(asList(5,6));
+    loader.setPrefetchQueue(5, 6);
     reqs.assertFragmentsRequested(5);
     progress.assertEvent("download5", BEGIN, 5);

@@ -510,10 +508,10 @@
     progress.assertEvent("download6", END, 6);
     progress.assertNoEvents();
     // request prefetches, then request different prefetches
-    loader.setPrefetchQueue(asList(8,9));
+    loader.setPrefetchQueue(8, 9);
     reqs.assertFragmentsRequested(8);
     progress.assertEvent("download8", BEGIN, 8);
-    loader.setPrefetchQueue(asList(10));
+    loader.setPrefetchQueue(10);
     reqs.assertFragmentsRequested();
     progress.assertNoEvents();

@@ -527,7 +525,7 @@
     progress.assertEvent("download10", END, 10);
     progress.assertNoEvents();
     // request prefetches that have already been loaded
-    loader.setPrefetchQueue(asList(1, 3, 7, 10));
+    loader.setPrefetchQueue(1, 3, 7, 10);
     reqs.assertFragmentsRequested();
     progress.assertNoEvents();
   }
@@ -543,7 +541,7 @@
         1, 2, 3}, reqs, progress);
     loader.startPrefetching();
     // request a prefetch of something in the initial load sequence
-    loader.setPrefetchQueue(asList(3, 2, 1));
+    loader.setPrefetchQueue(3, 2, 1);
     reqs.assertFragmentsRequested(1);
     progress.assertEvent("download1", BEGIN, 1);

@@ -589,7 +587,7 @@
         new int[] {}, reqs, progress);
     loader.stopPrefetching();
     // Prefetch 1, but leave prefetching off
-    loader.setPrefetchQueue(asList(1));
+    loader.setPrefetchQueue(1);
     reqs.assertFragmentsRequested();
     progress.assertNoEvents();

@@ -646,7 +644,7 @@
     progress.assertEvent("download1", END, 1);
     progress.assertNoEvents();
     // Start prefetching a fragment
-    loader.setPrefetchQueue(asList(2));
+    loader.setPrefetchQueue(2);
     reqs.assertFragmentsRequested(2);
     progress.assertEvent("download2", BEGIN, 2);

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors

Reply via email to