Revision: 7720
Author: gwt.mirror...@gmail.com
Date: Fri Mar 12 08:11:14 2010
Log: Fixing handling of nested switch statements in gflow.
Added couple of toString methods which helped debugging the issue.

Review by: sp...@google.com
http://code.google.com/p/google-web-toolkit/source/detail?r=7720

Modified:
 /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/AnalysisSolver.java
 /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/cfg/CfgBuilder.java
/trunk/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/constants/ConstantConditionTransformation.java /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/constants/FoldConstantsTransformation.java /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/unreachable/DeleteNodeTransformation.java
 /trunk/dev/core/test/com/google/gwt/dev/jjs/impl/OptimizerTestBase.java
/trunk/dev/core/test/com/google/gwt/dev/jjs/impl/gflow/DataflowOptimizerTest.java /trunk/dev/core/test/com/google/gwt/dev/jjs/impl/gflow/cfg/CfgBuilderTest.java

=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/AnalysisSolver.java Tue Mar 9 10:54:56 2010 +++ /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/AnalysisSolver.java Fri Mar 12 08:11:14 2010
@@ -83,8 +83,8 @@
       if (debug) {
         System.err.println("Applying transformation: " + transformation);
         System.err.println("Replacing");
-        System.err.println(graph);
-        System.err.println("With");
+        System.err.println(node);
+        System.err.println("With graph:");
         System.err.println(newSubgraph);
       }

@@ -271,6 +271,12 @@
    */
   private void iterate(G graph,
       final IntegratedAnalysis<N, E, T, G, A> integratedAnalysis) {
+    if (debug) {
+      System.err.println("-----------------------------------------");
+      System.err.println("Iterate started on:");
+      System.err.println(graph);
+      System.err.println("-----------------------------------------");
+    }
     final IntegratedFlowFunctionAdapter adapter =
       new IntegratedFlowFunctionAdapter(integratedAnalysis);

=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/cfg/CfgBuilder.java Tue Mar 9 10:54:56 2010 +++ /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/cfg/CfgBuilder.java Fri Mar 12 08:11:14 2010
@@ -610,12 +610,16 @@
       accept(x.getExpr());

       JSwitchStatement oldSwitchStatement = switchStatement;
+      // We don't want to mess with other case exits here
+      List<Exit> oldCaseElseExits = removeExits(Exit.Reason.CASE_ELSE);
+      List<Exit> oldCaseThenExits = removeExits(Exit.Reason.CASE_THEN);
+      List<Exit> oldBreakExits = removeExits(Exit.Reason.BREAK);
       switchStatement = x;

       int defaultPos = -1;

       List<Exit> breakExits = new ArrayList<Exit>();
-
+
       for (JStatement s : x.getBody().getStatements()) {
         if (s instanceof JCaseStatement) {
           if (((JCaseStatement) s).getExpr() != null) {
@@ -660,6 +664,9 @@
       }

       switchStatement = oldSwitchStatement;
+      addExits(oldCaseElseExits);
+      addExits(oldCaseThenExits);
+      addExits(oldBreakExits);
       popNode();
       return false;
     }
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/constants/ConstantConditionTransformation.java Tue Mar 9 10:54:56 2010 +++ /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/constants/ConstantConditionTransformation.java Fri Mar 12 08:11:14 2010
@@ -111,4 +111,10 @@

     return newSubgraph;
   }
-}
+
+  @Override
+  public String toString() {
+    return "ConstantConditionTransformation(node=" + node +
+        ", conditionValue=" + conditionValue + ")";
+  }
+}
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/constants/FoldConstantsTransformation.java Tue Mar 9 10:54:56 2010 +++ /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/constants/FoldConstantsTransformation.java Fri Mar 12 08:11:14 2010
@@ -52,4 +52,10 @@
     CfgNode<?> newNode = new CfgNopNode(node.getParent(), node.getJNode());
     return CfgUtil.createSingleNodeReplacementGraph(graph, node, newNode);
   }
-}
+
+  @Override
+  public String toString() {
+    return "FoldConstantsTransformation(node=" + node +
+        ", assumptions=" + assumption + ")";
+  }
+}
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/unreachable/DeleteNodeTransformation.java Tue Mar 9 10:54:56 2010 +++ /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/unreachable/DeleteNodeTransformation.java Fri Mar 12 08:11:14 2010
@@ -65,4 +65,9 @@
     CfgNode<?> newNode = new CfgNopNode(node.getParent(), node.getJNode());
     return CfgUtil.createSingleNodeReplacementGraph(graph, node, newNode);
   }
-}
+
+  @Override
+  public String toString() {
+    return "DeleteNodeTransformation(node=" + node + ")";
+  }
+}
=======================================
--- /trunk/dev/core/test/com/google/gwt/dev/jjs/impl/OptimizerTestBase.java Tue Mar 9 10:54:56 2010 +++ /trunk/dev/core/test/com/google/gwt/dev/jjs/impl/OptimizerTestBase.java Fri Mar 12 08:11:14 2010
@@ -231,5 +231,16 @@
"public class Exceptions { static boolean throwAssertionError() { throw new RuntimeException(); } }";
       }
     });
-}
-}
+
+    sourceOracle.addOrReplace(new MockJavaResource("java.lang.String") {
+      @Override
+      protected CharSequence getContent() {
+        return "package java.lang;" +
+          "public class String {" +
+          "  public int length() { return 0; }" +
+          "  public char charAt(int pos) { return 0; }" +
+          "}";
+      }
+    });
+  }
+}
=======================================
--- /trunk/dev/core/test/com/google/gwt/dev/jjs/impl/gflow/DataflowOptimizerTest.java Tue Mar 9 10:54:56 2010 +++ /trunk/dev/core/test/com/google/gwt/dev/jjs/impl/gflow/DataflowOptimizerTest.java Fri Mar 12 08:11:14 2010
@@ -181,6 +181,121 @@
             );
   }

+  public void testComplexCode3() throws Exception {
+    addSnippetClassDecl("static final int SPLIT_LOOKING_FOR_COMMA = 0;");
+    addSnippetClassDecl("static final int SPLIT_IN_STRING = 1;");
+    addSnippetClassDecl("static final int SPLIT_IN_ESCAPE = 2;");
+    addSnippetClassDecl("static String getCsvString() { return null; }");
+
+    addSnippetClassDecl(
+        "static class JsArrayString {" +
+        "  static JsArrayString createArray() { return null; }" +
+        "  JsArrayString cast() { return this; }" +
+        "  void push(String s) { }" +
+        "}");
+
+    addSnippetClassDecl(
+        "static class StringBuilder {" +
+        "  void append(char c) { }" +
+        "}");
+
+    optimize("JsArrayString",
+       "int state;",
+       "String csvString = getCsvString();",
+       "JsArrayString results = JsArrayString.createArray().cast();",
+       "int index = 0;",
+       "StringBuilder field = new StringBuilder();",
+       "state = SPLIT_LOOKING_FOR_COMMA;",
+       "while (index < csvString.length()) {",
+       "  char nextCharacter = csvString.charAt(index);",
+       "  switch (state) {",
+       "    case SPLIT_LOOKING_FOR_COMMA:",
+       "      switch (nextCharacter) {",
+       "        case ',':",
+       "          results.push(field.toString());",
+       "          field = new StringBuilder();",
+       "          break;",
+       "        case '\"':",
+       "          state = SPLIT_IN_STRING;",
+       "          break;",
+       "        default:",
+       "          field.append(nextCharacter);",
+       "      }",
+       "      break;",
+       "    case SPLIT_IN_STRING:",
+       "      switch (nextCharacter) {",
+       "        case '\"':",
+       "          state = SPLIT_LOOKING_FOR_COMMA;",
+       "          break;",
+       "        case '\\\\':",
+       "          state = SPLIT_IN_ESCAPE;",
+       "          field.append(nextCharacter);",
+       "          break;",
+       "        default:",
+       "          field.append(nextCharacter);",
+       "      }",
+       "      break;",
+       "    case SPLIT_IN_ESCAPE:",
+       "      state = SPLIT_IN_STRING;",
+       "      field.append(nextCharacter);",
+       "      break;",
+       "    default:",
+       "      field.append(nextCharacter);",
+       "  }",
+       "  index++;",
+       "}",
+       "results.push(field.toString());",
+       "return results;"
+   ).into(
+       "int state;",
+       "String csvString = getCsvString();",
+       "JsArrayString results = JsArrayString.createArray().cast();",
+       "int index = 0;",
+       "StringBuilder field = new StringBuilder();",
+       "state = SPLIT_LOOKING_FOR_COMMA;",
+       "while (index < csvString.length()) {",
+       "  char nextCharacter = csvString.charAt(index);",
+       "  switch (state) {",
+       "    case SPLIT_LOOKING_FOR_COMMA:",
+       "      switch (nextCharacter) {",
+       "        case ',':",
+       "          results.push(field.toString());",
+       "          field = new StringBuilder();",
+       "          break;",
+       "        case '\"':",
+       "          state = SPLIT_IN_STRING;",
+       "          break;",
+       "        default:",
+       "          field.append(nextCharacter);",
+       "      }",
+       "      break;",
+       "    case SPLIT_IN_STRING:",
+       "      switch (nextCharacter) {",
+       "        case '\"':",
+       "          state = SPLIT_LOOKING_FOR_COMMA;",
+       "          break;",
+       "        case '\\\\':",
+       "          state = SPLIT_IN_ESCAPE;",
+       "          field.append('\\\\');",
+       "          break;",
+       "        default:",
+       "          field.append(nextCharacter);",
+       "      }",
+       "      break;",
+       "    case SPLIT_IN_ESCAPE:",
+       "      state = SPLIT_IN_STRING;",
+       "      field.append(nextCharacter);",
+       "      break;",
+       "    default:",
+       "      field.append(nextCharacter);",
+       "  }",
+       "  ++index;",
+       "}",
+       "results.push(field.toString());",
+       "return results;"
+       );
+  }
+
 /*  public void testInlineField1() throws Exception {
     optimize("int",
         "int i = staticFooInstance.i;",
=======================================
--- /trunk/dev/core/test/com/google/gwt/dev/jjs/impl/gflow/cfg/CfgBuilderTest.java Tue Mar 9 10:54:56 2010 +++ /trunk/dev/core/test/com/google/gwt/dev/jjs/impl/gflow/cfg/CfgBuilderTest.java Fri Mar 12 08:11:14 2010
@@ -1134,6 +1134,89 @@
     );
   }

+  public void testNestedSwitch() throws Exception {
+    assertCfg("void",
+        "switch(i) {",
+        "  case 1: ",
+        "    switch (j) {",
+        "      case 0: k = 1; break;",
+        "      case 1: k = 2; break;",
+        "    }",
+        "    break;",
+        "  case 2: ",
+        "    switch (j) {",
+        "      case 0: k = 3; break;",
+        "      case 1: k = 4; break;",
+        "    }",
+        "    break;",
+        "  case 3: ",
+        "    switch (j) {",
+        "      case 0: k = 5; break;",
+        "      case 1: k = 6; break;",
+        "    }",
+        "    break;",
+        "}"
+        ).is(
+        "BLOCK -> [*]",
+        "STMT -> [*]",
+        "READ(i) -> [*]",
+        "STMT -> [*]",
+        "COND (EntryPoint.i == 1) -> [THEN=*, ELSE=3]",
+        "STMT -> [*]",
+        "READ(j) -> [*]",
+        "STMT -> [*]",
+        "COND (EntryPoint.j == 0) -> [THEN=*, ELSE=1]",
+        "STMT -> [*]",
+        "WRITE(k, 1) -> [*]",
+        "STMT -> [*]",
+        "GOTO -> [2]",
+        "1: STMT -> [*]",
+        "COND (EntryPoint.j == 1) -> [THEN=*, ELSE=2]",
+        "STMT -> [*]",
+        "WRITE(k, 2) -> [*]",
+        "STMT -> [*]",
+        "GOTO -> [*]",
+        "2: STMT -> [*]",
+        "GOTO -> [9]",
+        "3: STMT -> [*]",
+        "COND (EntryPoint.i == 2) -> [THEN=*, ELSE=6]",
+        "STMT -> [*]",
+        "READ(j) -> [*]",
+        "STMT -> [*]",
+        "COND (EntryPoint.j == 0) -> [THEN=*, ELSE=4]",
+        "STMT -> [*]",
+        "WRITE(k, 3) -> [*]",
+        "STMT -> [*]",
+        "GOTO -> [5]",
+        "4: STMT -> [*]",
+        "COND (EntryPoint.j == 1) -> [THEN=*, ELSE=5]",
+        "STMT -> [*]",
+        "WRITE(k, 4) -> [*]",
+        "STMT -> [*]",
+        "GOTO -> [*]",
+        "5: STMT -> [*]",
+        "GOTO -> [9]",
+        "6: STMT -> [*]",
+        "COND (EntryPoint.i == 3) -> [THEN=*, ELSE=9]",
+        "STMT -> [*]",
+        "READ(j) -> [*]",
+        "STMT -> [*]",
+        "COND (EntryPoint.j == 0) -> [THEN=*, ELSE=7]",
+        "STMT -> [*]",
+        "WRITE(k, 5) -> [*]",
+        "STMT -> [*]",
+        "GOTO -> [8]",
+        "7: STMT -> [*]",
+        "COND (EntryPoint.j == 1) -> [THEN=*, ELSE=8]",
+        "STMT -> [*]",
+        "WRITE(k, 6) -> [*]",
+        "STMT -> [*]",
+        "GOTO -> [*]",
+        "8: STMT -> [*]",
+        "GOTO -> [*]",
+        "9: END"
+    );
+  }
   public void testSwitchWithLoopAndBreak() throws Exception {
     assertCfg("void",
         "switch(i) {",

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

Reply via email to