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 <stal...@google.com>

--
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 google-web-toolkit-contributors+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to