Revision: 7939
Author: [email protected]
Date: Mon Apr 19 10:12:50 2010
Log: Cherry picking r7934 from trunk, with this command:

svn merge --ignore-ancestry -c 7934 https://google-web-toolkit.googlecode.com/svn/trunk .

This fixes a problem with switch statements that begin with their default case.


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

Added:
/branches/snapshot-2010.03.29-r7809/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/cfg/CfgSwitchGotoNode.java
Modified:
/branches/snapshot-2010.03.29-r7809/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/cfg/CfgBuilder.java /branches/snapshot-2010.03.29-r7809/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/cfg/CfgVisitor.java /branches/snapshot-2010.03.29-r7809/dev/core/test/com/google/gwt/dev/jjs/impl/gflow/cfg/CfgBuilderTest.java

=======================================
--- /dev/null
+++ /branches/snapshot-2010.03.29-r7809/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/cfg/CfgSwitchGotoNode.java Mon Apr 19 10:12:50 2010
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2010 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.gflow.cfg;
+
+import com.google.gwt.dev.jjs.ast.JSwitchStatement;
+
+/**
+ * Goto to first switch case statement.
+ */
+public class CfgSwitchGotoNode extends CfgGotoNode<JSwitchStatement> {
+  public CfgSwitchGotoNode(CfgNode<?> parent, JSwitchStatement node) {
+    super(parent, node);
+  }
+
+  @Override
+  public void accept(CfgVisitor visitor) {
+    visitor.visitSwitchGotoNode(this);
+  }
+
+  @Override
+  protected CfgNode<?> cloneImpl() {
+    return new CfgSwitchGotoNode(getParent(), getJNode());
+  }
+}
=======================================
--- /branches/snapshot-2010.03.29-r7809/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/cfg/CfgBuilder.java Fri Mar 12 08:11:14 2010 +++ /branches/snapshot-2010.03.29-r7809/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/cfg/CfgBuilder.java Mon Apr 19 10:12:50 2010
@@ -606,7 +606,6 @@
     @Override
     public boolean visit(JSwitchStatement x, Context ctx) {
       pushNode(new CfgStatementNode<JStatement>(parent, x));
-      // TODO: Add statement node
       accept(x.getExpr());

       JSwitchStatement oldSwitchStatement = switchStatement;
@@ -615,15 +614,26 @@
       List<Exit> oldCaseThenExits = removeExits(Exit.Reason.CASE_THEN);
       List<Exit> oldBreakExits = removeExits(Exit.Reason.BREAK);
       switchStatement = x;
+
+      // Goto to the first non-default node.
+ CfgSwitchGotoNode gotoNode = addNode(new CfgSwitchGotoNode(parent, x));
+      Exit gotoExit = Exit.createNormal(gotoNode, null);

       int defaultPos = -1;

       List<Exit> breakExits = new ArrayList<Exit>();

-      for (JStatement s : x.getBody().getStatements()) {
+      List<JStatement> statements = x.getBody().getStatements();
+
+      for (JStatement s : statements) {
         if (s instanceof JCaseStatement) {
           if (((JCaseStatement) s).getExpr() != null) {
             // case label
+            if (gotoExit != null) {
+              // This is first non-default case.
+              addExit(gotoExit);
+              gotoExit = null;
+            }
             List<Exit> elseExits = removeExits(Exit.Reason.CASE_ELSE);
             for (Exit e : elseExits) {
               addNormalExit(e.getNode(), e.role);
@@ -641,6 +651,16 @@
         accept(s);
         breakExits.addAll(removeExits(Exit.Reason.BREAK));
       }
+
+      if (gotoExit != null) {
+        // Happens when there are no case statements.
+        if (defaultPos >= 0) {
+          addEdge(gotoExit, nodes.get(defaultPos));
+        } else {
+          addExit(gotoExit);
+        }
+        gotoExit = null;
+      }

       List<Exit> thenExits = removeExits(Exit.Reason.CASE_THEN);
       for (Exit e : thenExits) {
=======================================
--- /branches/snapshot-2010.03.29-r7809/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/cfg/CfgVisitor.java Tue Mar 9 10:54:56 2010 +++ /branches/snapshot-2010.03.29-r7809/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/cfg/CfgVisitor.java Mon Apr 19 10:12:50 2010
@@ -104,6 +104,10 @@
   public void visitStatementNode(CfgStatementNode<?> node) {
     visitSimpleNode(node);
   }
+
+  public void visitSwitchGotoNode(CfgSwitchGotoNode node) {
+    visitGotoNode(node);
+  }

   public void visitThrowNode(CfgThrowNode node) {
     visitNode(node);
=======================================
--- /branches/snapshot-2010.03.29-r7809/dev/core/test/com/google/gwt/dev/jjs/impl/gflow/cfg/CfgBuilderTest.java Fri Mar 12 08:11:14 2010 +++ /branches/snapshot-2010.03.29-r7809/dev/core/test/com/google/gwt/dev/jjs/impl/gflow/cfg/CfgBuilderTest.java Mon Apr 19 10:12:50 2010
@@ -1105,6 +1105,7 @@
             "BLOCK -> [*]",
             "STMT -> [*]",
             "READ(i) -> [*]",
+            "GOTO -> [*]",
             "STMT -> [*]",
             "COND (EntryPoint.i == 1) -> [THEN=*, ELSE=1]",
             "STMT -> [*]",
@@ -1134,6 +1135,63 @@
     );
   }

+  public void testSwitch_FirstDefault() throws Exception {
+    assertCfg("void",
+        "switch(i) {",
+        "  default: j = 1; return;",
+        "  case 1: j = 2; return;",
+        "}"
+        ).is(
+            "BLOCK -> [*]",
+            "STMT -> [*]",
+            "READ(i) -> [*]",
+            "GOTO -> [2]",
+            "1: STMT -> [*]",
+            "STMT -> [*]",
+            "WRITE(j, 1) -> [*]",
+            "STMT -> [*]",
+            "GOTO -> [3]",
+            "2: STMT -> [*]",
+            "COND (EntryPoint.i == 1) -> [THEN=*, ELSE=1]",
+            "STMT -> [*]",
+            "WRITE(j, 2) -> [*]",
+            "STMT -> [*]",
+            "GOTO -> [*]",
+            "3: END"
+    );
+  }
+
+  public void testSwitch_Empty() throws Exception {
+    assertCfg("void",
+        "switch(i) {",
+        "}"
+        ).is(
+            "BLOCK -> [*]",
+            "STMT -> [*]",
+            "READ(i) -> [*]",
+            "GOTO -> [*]",
+            "END"
+    );
+  }
+
+  public void testSwitch_OnlyDefault() throws Exception {
+    assertCfg("void",
+        "switch(i) {",
+        "  default: j = 0; return;",
+        "}"
+        ).is(
+            "BLOCK -> [*]",
+            "STMT -> [*]",
+            "READ(i) -> [*]",
+            "GOTO -> [*]",
+            "STMT -> [*]",
+            "STMT -> [*]",
+            "WRITE(j, 0) -> [*]",
+            "STMT -> [*]",
+            "GOTO -> [*]",
+            "END"
+    );
+  }
   public void testNestedSwitch() throws Exception {
     assertCfg("void",
         "switch(i) {",
@@ -1160,10 +1218,12 @@
         "BLOCK -> [*]",
         "STMT -> [*]",
         "READ(i) -> [*]",
+        "GOTO -> [*]",
         "STMT -> [*]",
         "COND (EntryPoint.i == 1) -> [THEN=*, ELSE=3]",
         "STMT -> [*]",
         "READ(j) -> [*]",
+        "GOTO -> [*]",
         "STMT -> [*]",
         "COND (EntryPoint.j == 0) -> [THEN=*, ELSE=1]",
         "STMT -> [*]",
@@ -1182,6 +1242,7 @@
         "COND (EntryPoint.i == 2) -> [THEN=*, ELSE=6]",
         "STMT -> [*]",
         "READ(j) -> [*]",
+        "GOTO -> [*]",
         "STMT -> [*]",
         "COND (EntryPoint.j == 0) -> [THEN=*, ELSE=4]",
         "STMT -> [*]",
@@ -1200,6 +1261,7 @@
         "COND (EntryPoint.i == 3) -> [THEN=*, ELSE=9]",
         "STMT -> [*]",
         "READ(j) -> [*]",
+        "GOTO -> [*]",
         "STMT -> [*]",
         "COND (EntryPoint.j == 0) -> [THEN=*, ELSE=7]",
         "STMT -> [*]",
@@ -1231,6 +1293,7 @@
             "BLOCK -> [*]",
             "STMT -> [*]",
             "READ(i) -> [*]",
+            "GOTO -> [*]",
             "STMT -> [*]",
             "COND (EntryPoint.i == 1) -> [THEN=*, ELSE=1]",
             "STMT -> [*]",

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

Reply via email to