1 16 package com.google.gwt.dev.jjs.impl; 17 18 import com.google.gwt.dev.jjs.ast.Context; 19 import com.google.gwt.dev.jjs.ast.JArrayRef; 20 import com.google.gwt.dev.jjs.ast.JBinaryOperation; 21 import com.google.gwt.dev.jjs.ast.JBinaryOperator; 22 import com.google.gwt.dev.jjs.ast.JExpression; 23 import com.google.gwt.dev.jjs.ast.JFieldRef; 24 import com.google.gwt.dev.jjs.ast.JLocal; 25 import com.google.gwt.dev.jjs.ast.JLocalRef; 26 import com.google.gwt.dev.jjs.ast.JMethod; 27 import com.google.gwt.dev.jjs.ast.JModVisitor; 28 import com.google.gwt.dev.jjs.ast.JNullLiteral; 29 import com.google.gwt.dev.jjs.ast.JParameterRef; 30 import com.google.gwt.dev.jjs.ast.JProgram; 31 import com.google.gwt.dev.jjs.ast.JThisRef; 32 import com.google.gwt.dev.jjs.ast.js.JMultiExpression; 33 34 import java.util.ArrayList ; 35 import java.util.List ; 36 37 42 public class CompoundAssignmentNormalizer { 43 44 47 private class BreakupAssignOpsVisitor extends JModVisitor { 48 49 public void endVisit(JBinaryOperation x, Context ctx) { 51 57 if (x.getOp() == JBinaryOperator.ASG_DIV 58 && x.getType() != program.getTypePrimitiveFloat() 59 && x.getType() != program.getTypePrimitiveDouble()) { 60 61 67 final int pushUsedLocals = localIndex; 68 JMultiExpression multi = new JMultiExpression(program, 69 x.getSourceInfo()); 70 ReplaceSideEffectsInLvalue replacer = new ReplaceSideEffectsInLvalue( 71 multi); 72 JExpression newLhs = replacer.accept(x.getLhs()); 73 localIndex = pushUsedLocals; 74 75 JNullLiteral litNull = program.getLiteralNull(); 76 JBinaryOperation operation = new JBinaryOperation(program, 77 x.getSourceInfo(), newLhs.getType(), JBinaryOperator.DIV, newLhs, 78 x.getRhs()); 79 JBinaryOperation asg = new JBinaryOperation(program, x.getSourceInfo(), 80 newLhs.getType(), JBinaryOperator.ASG, newLhs, operation); 81 82 JMultiExpression multiExpr = replacer.getMultiExpr(); 83 if (multiExpr.exprs.isEmpty()) { 84 ctx.replaceMe(asg); 86 } else { 87 multi.exprs.add(asg); 89 ctx.replaceMe(multi); 90 } 91 } 92 } 93 94 public void endVisit(JMethod x, Context ctx) { 96 clearLocals(); 97 currentMethod = null; 98 } 99 100 public boolean visit(JMethod x, Context ctx) { 102 currentMethod = x; 103 clearLocals(); 104 return true; 105 } 106 } 107 110 private class ReplaceSideEffectsInLvalue extends JModVisitor { 111 112 private final JMultiExpression multi; 113 114 ReplaceSideEffectsInLvalue(JMultiExpression multi) { 115 this.multi = multi; 116 } 117 118 public JMultiExpression getMultiExpr() { 119 return multi; 120 } 121 122 public boolean visit(JArrayRef x, Context ctx) { 124 JExpression newInstance = possiblyReplace(x.getInstance()); 125 JExpression newIndexExpr = possiblyReplace(x.getIndexExpr()); 126 if (newInstance != x.getInstance() || newIndexExpr != x.getIndexExpr()) { 127 JArrayRef newExpr = new JArrayRef(program, x.getSourceInfo(), 128 newInstance, newIndexExpr); 129 ctx.replaceMe(newExpr); 130 } 131 return false; 132 } 133 134 public boolean visit(JFieldRef x, Context ctx) { 136 if (x.getInstance() != null) { 137 JExpression newInstance = possiblyReplace(x.getInstance()); 138 if (newInstance != x.getInstance()) { 139 JFieldRef newExpr = new JFieldRef(program, x.getSourceInfo(), 140 newInstance, x.getField(), x.getEnclosingType()); 141 ctx.replaceMe(newExpr); 142 } 143 } 144 return false; 145 } 146 147 public boolean visit(JLocalRef x, Context ctx) { 149 return false; 150 } 151 152 public boolean visit(JParameterRef x, Context ctx) { 154 return false; 155 } 156 157 public boolean visit(JThisRef x, Context ctx) { 159 return false; 160 } 161 162 private JExpression possiblyReplace(JExpression x) { 163 if (!x.hasSideEffects()) { 164 return x; 165 } 166 167 JLocal tempLocal = getTempLocal(); 169 170 JLocalRef tempRef = new JLocalRef(program, x.getSourceInfo(), tempLocal); 172 JBinaryOperation asg = new JBinaryOperation(program, x.getSourceInfo(), 173 x.getType(), JBinaryOperator.ASG, tempRef, x); 174 multi.exprs.add(asg); 175 return tempRef; 177 } 178 } 179 180 public static void exec(JProgram program) { 181 new CompoundAssignmentNormalizer(program).execImpl(); 182 } 183 184 private JMethod currentMethod; 185 private int localIndex; 186 private final JProgram program; 187 private final List tempLocals = new ArrayList (); 188 189 private CompoundAssignmentNormalizer(JProgram program) { 190 this.program = program; 191 } 192 193 private void clearLocals() { 194 tempLocals.clear(); 195 localIndex = 0; 196 } 197 198 private void execImpl() { 199 BreakupAssignOpsVisitor breaker = new BreakupAssignOpsVisitor(); 200 breaker.accept(program); 201 } 202 203 private JLocal getTempLocal() { 204 if (localIndex < tempLocals.size()) { 205 return (JLocal) tempLocals.get(localIndex++); 206 } 207 JLocal newTemp = program.createLocal(null, 208 ("$t" + localIndex++).toCharArray(), program.getTypeVoid(), false, 209 currentMethod); 210 tempLocals.add(newTemp); 211 return newTemp; 212 } 213 214 } 215 | Popular Tags |