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