Separates the ADD binary operation into two separate operations,
one for string append and one for numeric addition.

Review by: scottb


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@5994 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JBinaryOperator.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JBinaryOperator.java
index 1922711..e4a18fc 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JBinaryOperator.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JBinaryOperator.java
@@ -24,11 +24,10 @@
 
   // Don't renumber precs without checking implementation of isShiftOperator()
 
-  MUL("*", 3), DIV("/", 3), MOD("%", 3), ADD("+", 4), SUB("-", 4), SHL("<<", 5), SHR(
+  MUL("*", 3), DIV("/", 3), MOD("%", 3), ADD("+", 4), CONCAT("+", 4), SUB("-", 4), SHL("<<", 5), SHR(
       ">>", 5), SHRU(">>>", 5), LT("<", 6), LTE("<=", 6), GT(">", 6), GTE(">=",
       6), EQ("==", 7), NEQ("!=", 7), BIT_AND("&", 8), BIT_XOR("^", 9), BIT_OR(
-      "|", 10), AND("&&", 11), OR("||", 12), ASG("=", 14), ASG_ADD("+=", 14,
-      ADD), ASG_SUB("-=", 14, SUB), ASG_MUL("*=", 14, MUL), ASG_DIV("/=", 14,
+      "|", 10), AND("&&", 11), OR("||", 12), ASG("=", 14), ASG_ADD("+=", 14, ADD), ASG_CONCAT("+=", 14, CONCAT), ASG_SUB("-=", 14, SUB), ASG_MUL("*=", 14, MUL), ASG_DIV("/=", 14,
       DIV), ASG_MOD("%=", 14, MOD), ASG_SHL("<<=", 14, SHL), ASG_SHR(">>=", 14,
       SHR), ASG_SHRU(">>>=", 14, SHRU), ASG_BIT_AND("&=", 14, BIT_AND), ASG_BIT_OR(
       "|=", 14, BIT_OR), ASG_BIT_XOR("^=", 14, BIT_XOR);
@@ -68,6 +67,7 @@
     return precedence == 5 || (nonAsg != null && nonAsg.precedence == 5);
   }
 
+  @Override
   public String toString() {
     return new String(getSymbol());
   }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/CastNormalizer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/CastNormalizer.java
index 1319526..4296607 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/CastNormalizer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/CastNormalizer.java
@@ -329,24 +329,20 @@
 
     @Override
     public void endVisit(JBinaryOperation x, Context ctx) {
-      if (x.getType() != program.getTypeJavaLangString()) {
-        return;
-      }
-
-      if (x.getOp() == JBinaryOperator.ADD) {
+      if (x.getOp() == JBinaryOperator.CONCAT) {
         JExpression newLhs = convertString(x.getLhs());
         JExpression newRhs = convertString(x.getRhs());
         if (newLhs != x.getLhs() || newRhs != x.getRhs()) {
           JBinaryOperation newExpr = new JBinaryOperation(x.getSourceInfo(),
-              program.getTypeJavaLangString(), JBinaryOperator.ADD, newLhs,
+              program.getTypeJavaLangString(), JBinaryOperator.CONCAT, newLhs,
               newRhs);
           ctx.replaceMe(newExpr);
         }
-      } else if (x.getOp() == JBinaryOperator.ASG_ADD) {
+      } else if (x.getOp() == JBinaryOperator.ASG_CONCAT) {
         JExpression newRhs = convertString(x.getRhs());
         if (newRhs != x.getRhs()) {
           JBinaryOperation newExpr = new JBinaryOperation(x.getSourceInfo(),
-              program.getTypeJavaLangString(), JBinaryOperator.ASG_ADD,
+              program.getTypeJavaLangString(), JBinaryOperator.ASG_CONCAT,
               x.getLhs(), newRhs);
           ctx.replaceMe(newExpr);
         }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/ControlFlowAnalyzer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/ControlFlowAnalyzer.java
index 906fba5..446a52e 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/ControlFlowAnalyzer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/ControlFlowAnalyzer.java
@@ -128,8 +128,7 @@
       }
 
       // special string concat handling
-      if ((x.getOp() == JBinaryOperator.ADD || x.getOp() == JBinaryOperator.ASG_ADD)
-          && x.getType() == program.getTypeJavaLangString()) {
+      if ((x.getOp() == JBinaryOperator.CONCAT || x.getOp() == JBinaryOperator.ASG_CONCAT)) {
         rescueByConcat(x.getLhs().getType());
         rescueByConcat(x.getRhs().getType());
       } else if (x.getOp() == JBinaryOperator.ASG) {
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java b/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java
index a8643a2..dfed1e2 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java
@@ -155,12 +155,11 @@
           simplifyEq(lhs, rhs, ctx, true);
           break;
         case ADD:
-          if (x.getType() == program.getTypeJavaLangString()) {
-            evalConcat(lhs, rhs, ctx);
-            break;
-          }
           simplifyAdd(lhs, rhs, ctx, x.getType());
           break;
+        case CONCAT:
+          evalConcat(lhs, rhs, ctx);
+          break;
         case SUB:
           simplifySub(lhs, rhs, ctx, x.getType());
           break;
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java
index 511f422..3b74a87 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java
@@ -907,7 +907,11 @@
           op = JBinaryOperator.SHRU;
           break;
         case BinaryExpression.PLUS:
-          op = JBinaryOperator.ADD;
+          if (typeMap.get(x.resolvedType) == program.getTypeJavaLangString()) {
+            op = JBinaryOperator.CONCAT;
+          } else {
+            op = JBinaryOperator.ADD;
+          }
           break;
         case BinaryExpression.MINUS:
           op = JBinaryOperator.SUB;
@@ -974,7 +978,11 @@
 
       switch (x.operator) {
         case CompoundAssignment.PLUS:
-          op = JBinaryOperator.ASG_ADD;
+          if (typeMap.get(x.resolvedType) == program.getTypeJavaLangString()) {
+            op = JBinaryOperator.ASG_CONCAT;
+          } else {
+            op = JBinaryOperator.ASG_ADD;
+          }
           break;
         case CompoundAssignment.MINUS:
           op = JBinaryOperator.ASG_SUB;
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
index 4acb98f..a42463c 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
@@ -1763,6 +1763,7 @@
       bOpMap.put(JBinaryOperator.DIV, JsBinaryOperator.DIV);
       bOpMap.put(JBinaryOperator.MOD, JsBinaryOperator.MOD);
       bOpMap.put(JBinaryOperator.ADD, JsBinaryOperator.ADD);
+      bOpMap.put(JBinaryOperator.CONCAT, JsBinaryOperator.ADD);
       bOpMap.put(JBinaryOperator.SUB, JsBinaryOperator.SUB);
       bOpMap.put(JBinaryOperator.SHL, JsBinaryOperator.SHL);
       bOpMap.put(JBinaryOperator.SHR, JsBinaryOperator.SHR);
@@ -1780,6 +1781,7 @@
       bOpMap.put(JBinaryOperator.OR, JsBinaryOperator.OR);
       bOpMap.put(JBinaryOperator.ASG, JsBinaryOperator.ASG);
       bOpMap.put(JBinaryOperator.ASG_ADD, JsBinaryOperator.ASG_ADD);
+      bOpMap.put(JBinaryOperator.ASG_CONCAT, JsBinaryOperator.ASG_ADD);
       bOpMap.put(JBinaryOperator.ASG_SUB, JsBinaryOperator.ASG_SUB);
       bOpMap.put(JBinaryOperator.ASG_MUL, JsBinaryOperator.ASG_MUL);
       bOpMap.put(JBinaryOperator.ASG_DIV, JsBinaryOperator.ASG_DIV);