John Stalcup has uploaded a new change for review.

  https://gwt-review.googlesource.com/3520


Change subject: replaces stale jProgram runAsync references and fixes JRunAsync method inlining to occasionally benefit from tighter types
......................................................................

replaces stale jProgram runAsync references and fixes JRunAsync method inlining to occasionally benefit from tighter types

Change-Id: I930a31272a5f9b689e8cb68971d7ffb77389488a
---
M dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
M dev/core/src/com/google/gwt/dev/jjs/ast/JRunAsync.java
M dev/core/src/com/google/gwt/dev/jjs/impl/CloneExpressionVisitor.java
M dev/core/src/com/google/gwt/dev/jjs/impl/MakeCallsStatic.java
M dev/core/src/com/google/gwt/dev/jjs/impl/MethodInliner.java
M dev/core/src/com/google/gwt/dev/jjs/impl/ReplaceRunAsyncs.java
A dev/core/src/com/google/gwt/dev/jjs/impl/RunAsyncsTightener.java
7 files changed, 116 insertions(+), 4 deletions(-)



diff --git a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
index 78fb2ca..ae47527 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
@@ -97,6 +97,7 @@
 import com.google.gwt.dev.jjs.impl.ReplaceGetClassOverrides;
 import com.google.gwt.dev.jjs.impl.ReplaceRunAsyncs;
 import com.google.gwt.dev.jjs.impl.ResolveRebinds;
+import com.google.gwt.dev.jjs.impl.RunAsyncsTightener;
 import com.google.gwt.dev.jjs.impl.SameParameterValueOptimizer;
 import com.google.gwt.dev.jjs.impl.SourceInfoCorrelator;
 import com.google.gwt.dev.jjs.impl.TypeTightener;
@@ -350,6 +351,8 @@
// prune all Object.getClass() overrides and replace with inline field ref
       ReplaceGetClassOverrides.exec(jprogram);

+      RunAsyncsTightener.exec(jprogram);
+
       // (7) Generate a JavaScript code DOM from the Java type declarations
       jprogram.typeOracle.recomputeAfterOptimizations();
       Pair<? extends JavaToJavaScriptMap, Set<JsNode>> genAstResult =
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JRunAsync.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JRunAsync.java
index 50cd058..9cc0a39 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JRunAsync.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JRunAsync.java
@@ -82,6 +82,14 @@
     return true;
   }

+  public void setOnSuccessCall(JExpression onSuccessCall) {
+    this.onSuccessCall = onSuccessCall;
+  }
+
+  public void setRunAsyncCall(JExpression runAsyncCall) {
+    this.runAsyncCall = runAsyncCall;
+  }
+
   public void traverse(JVisitor visitor, Context ctx) {
     if (visitor.visit(this, ctx)) {
       /*
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/CloneExpressionVisitor.java b/dev/core/src/com/google/gwt/dev/jjs/impl/CloneExpressionVisitor.java
index d1089da..26c2e15 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/CloneExpressionVisitor.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/CloneExpressionVisitor.java
@@ -227,11 +227,10 @@

   @Override
   public boolean visit(JRunAsync x, Context ctx) {
- // Only the runAsync call itself needs cloning, the onSuccess can be shared.
     JExpression runAsyncCall = cloneExpression(x.getRunAsyncCall());
-    expression =
- new JRunAsync(x.getSourceInfo(), x.getSplitPoint(), x.getName(), runAsyncCall, x
-            .getOnSuccessCall());
+    JExpression onSuccessCall = cloneExpression(x.getOnSuccessCall());
+    expression = new JRunAsync(
+ x.getSourceInfo(), x.getSplitPoint(), x.getName(), runAsyncCall, onSuccessCall);
     return false;
   }

diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/MakeCallsStatic.java b/dev/core/src/com/google/gwt/dev/jjs/impl/MakeCallsStatic.java
index 88cfd1c..3132ef0 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/MakeCallsStatic.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/MakeCallsStatic.java
@@ -30,6 +30,7 @@
 import com.google.gwt.dev.jjs.ast.JParameterRef;
 import com.google.gwt.dev.jjs.ast.JProgram;
 import com.google.gwt.dev.jjs.ast.JReturnStatement;
+import com.google.gwt.dev.jjs.ast.JRunAsync;
 import com.google.gwt.dev.jjs.ast.JStatement;
 import com.google.gwt.dev.jjs.ast.JThisRef;
 import com.google.gwt.dev.jjs.ast.JType;
@@ -113,6 +114,13 @@
       }

       @Override
+      public boolean visit(JRunAsync x, Context ctx) {
+        x.setRunAsyncCall(accept(x.getRunAsyncCall()));
+        x.setOnSuccessCall(accept(x.getOnSuccessCall()));
+        return false;
+      }
+
+      @Override
       public void endVisit(JParameterRef x, Context ctx) {
         JParameter param = varMap.get(x.getTarget());
JParameterRef paramRef = new JParameterRef(x.getSourceInfo(), param); diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/MethodInliner.java b/dev/core/src/com/google/gwt/dev/jjs/impl/MethodInliner.java
index d2b05ae..49f406a 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/MethodInliner.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/MethodInliner.java
@@ -32,6 +32,7 @@
 import com.google.gwt.dev.jjs.ast.JProgram;
 import com.google.gwt.dev.jjs.ast.JReferenceType;
 import com.google.gwt.dev.jjs.ast.JReturnStatement;
+import com.google.gwt.dev.jjs.ast.JRunAsync;
 import com.google.gwt.dev.jjs.ast.JStatement;
 import com.google.gwt.dev.jjs.ast.JThisRef;
 import com.google.gwt.dev.jjs.ast.JType;
@@ -457,6 +458,13 @@
     }

     @Override
+    public boolean visit(JRunAsync x, Context ctx) {
+      x.setRunAsyncCall(accept(x.getRunAsyncCall()));
+      x.setOnSuccessCall(accept(x.getOnSuccessCall()));
+      return false;
+    }
+
+    @Override
     public void endVisit(JParameterRef x, Context ctx) {
int paramIndex = methodCall.getTarget().getParams().indexOf(x.getParameter());
       assert paramIndex != -1;
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/ReplaceRunAsyncs.java b/dev/core/src/com/google/gwt/dev/jjs/impl/ReplaceRunAsyncs.java
index 2f50843..73cfaf5 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/ReplaceRunAsyncs.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/ReplaceRunAsyncs.java
@@ -117,6 +117,13 @@
               + "be passed to runAsync().");
           return;
         }
+
+ // It's illegal for two nodes in the AST to refer to the same node and doing so will cause + // some visitors to run improperly. Duplicate asyncCallback before adding this second
+        // reference in onSuccessCall.
+        CloneExpressionVisitor cloner = new CloneExpressionVisitor();
+        asyncCallback = cloner.cloneExpression(asyncCallback);
+
JMethodCall onSuccessCall = new JMethodCall(info, asyncCallback, callbackMethod);

JRunAsync runAsyncNode = new JRunAsync(info, splitPoint, name, runAsyncCall, onSuccessCall);
@@ -139,6 +146,7 @@
           && method.getName().equals("runAsync");
     }
   }
+
   private class ReplaceRunAsyncResources extends JModVisitor {
     private final Map<String, List<JRunAsync>> replacementsByName;
     private final JMethod runAsyncCode;
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/RunAsyncsTightener.java b/dev/core/src/com/google/gwt/dev/jjs/impl/RunAsyncsTightener.java
new file mode 100644
index 0000000..d442e8e
--- /dev/null
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/RunAsyncsTightener.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.dev.jjs.impl;
+
+import com.google.gwt.dev.jjs.ast.Context;
+import com.google.gwt.dev.jjs.ast.JProgram;
+import com.google.gwt.dev.jjs.ast.JRunAsync;
+import com.google.gwt.dev.jjs.ast.JVisitor;
+import com.google.gwt.thirdparty.guava.common.collect.LinkedHashMultimap;
+import com.google.gwt.thirdparty.guava.common.collect.Lists;
+import com.google.gwt.thirdparty.guava.common.collect.Multimap;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Replaces some JProgram references to JRunAsync nodes after optimization to take advantage of
+ * tighter types.
+ */
+public class RunAsyncsTightener {
+
+  private static class RunAsyncsGathererVisitor extends JVisitor {
+ // Is a Multimap not a Map because after optimization there can be duplicate versions
+    // of the same splitPoint in different contexts.
+ private Multimap<Integer, JRunAsync> optimizedRunAsyncListsBySplitPoint =
+        LinkedHashMultimap.create();
+
+    @Override
+    public boolean visit(JRunAsync runAsync, Context ctx) {
+ optimizedRunAsyncListsBySplitPoint.put(runAsync.getSplitPoint(), runAsync);
+      return super.visit(runAsync, ctx);
+    }
+  }
+
+  public static void exec(JProgram jProgram) {
+ RunAsyncsGathererVisitor runAsyncsGathererVisitor = new RunAsyncsGathererVisitor();
+    runAsyncsGathererVisitor.accept(jProgram);
+
+    List<JRunAsync> updatedRunAsyncs = Lists.newArrayList();
+    for (JRunAsync originalRunAsync : jProgram.getRunAsyncs()) {
+      Collection<JRunAsync> optimizedRunAsyncs =
+          runAsyncsGathererVisitor.optimizedRunAsyncListsBySplitPoint.get(
+              originalRunAsync.getSplitPoint());
+
+      int optimizedRunAsyncCount = optimizedRunAsyncs.size();
+ // If after optimization there is still only one copy of a particular runAsync.
+      if (optimizedRunAsyncCount == 1) {
+ // Then use the optimized version of it since the optimized version may now have a tighter + // RunAsyncCallback type that will allow CodeSplitting to place code more locally.
+        JRunAsync optimizedRunAsync = optimizedRunAsyncs.iterator().next();
+        updatedRunAsyncs.add(optimizedRunAsync);
+      } else {
+ // Expanding an original runAsync into multiple runAsyncs could actually expand the leftOver + // fragment by causing some code to appear to be reachable from multiple runAsyncs. + // CodeSplitter2 fragmentMerging could clean this back up automatically but there's no need + // to add this computation overhead nor end-user tweaking. Just keep the original
+        // non-duplicated runAsync.
+        updatedRunAsyncs.add(originalRunAsync);
+        continue;
+      }
+    }
+
+    jProgram.setRunAsyncs(updatedRunAsyncs);
+  }
+}

--
To view, visit https://gwt-review.googlesource.com/3520
To unsubscribe, visit https://gwt-review.googlesource.com/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I930a31272a5f9b689e8cb68971d7ffb77389488a
Gerrit-PatchSet: 1
Gerrit-Project: gwt
Gerrit-Branch: master
Gerrit-Owner: John Stalcup <[email protected]>

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors
--- You received this message because you are subscribed to the Google Groups "GWT Contributors" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to