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.JAbsentArrayDimension; 20 import com.google.gwt.dev.jjs.ast.JArrayRef; 21 import com.google.gwt.dev.jjs.ast.JArrayType; 22 import com.google.gwt.dev.jjs.ast.JBinaryOperation; 23 import com.google.gwt.dev.jjs.ast.JBinaryOperator; 24 import com.google.gwt.dev.jjs.ast.JExpression; 25 import com.google.gwt.dev.jjs.ast.JLiteral; 26 import com.google.gwt.dev.jjs.ast.JMethod; 27 import com.google.gwt.dev.jjs.ast.JMethodCall; 28 import com.google.gwt.dev.jjs.ast.JModVisitor; 29 import com.google.gwt.dev.jjs.ast.JNewArray; 30 import com.google.gwt.dev.jjs.ast.JNullType; 31 import com.google.gwt.dev.jjs.ast.JProgram; 32 import com.google.gwt.dev.jjs.ast.JReferenceType; 33 import com.google.gwt.dev.jjs.ast.JType; 34 import com.google.gwt.dev.jjs.ast.js.JsonArray; 35 36 41 public class ArrayNormalizer { 42 43 private class ArrayVisitor extends JModVisitor { 44 45 public void endVisit(JBinaryOperation x, Context ctx) { 47 if (x.getOp() == JBinaryOperator.ASG && x.getLhs() instanceof JArrayRef) { 48 JArrayRef arrayRef = (JArrayRef) x.getLhs(); 49 if (arrayRef.getType() instanceof JNullType) { 50 return; 52 } 53 JArrayType arrayType = (JArrayType) arrayRef.getInstance().getType(); 54 JType elementType = arrayType.getElementType(); 55 56 if (elementType instanceof JReferenceType 59 && (!((JReferenceType) elementType).isFinal()) 60 || elementType != x.getRhs().getType()) { 61 63 JMethodCall call = new JMethodCall(program, x.getSourceInfo(), null, 64 setCheckMethod); 65 call.getArgs().add(arrayRef.getInstance()); 66 call.getArgs().add(arrayRef.getIndexExpr()); 67 call.getArgs().add(x.getRhs()); 68 ctx.replaceMe(call); 69 } 70 } 71 } 72 73 public void endVisit(JNewArray x, Context ctx) { 75 JArrayType type = x.getArrayType(); 76 JLiteral litTypeName = program.getLiteralString(calcClassName(type)); 77 78 if (x.initializers != null) { 79 processInitializers(x, ctx, type, litTypeName); 80 } else { 81 processDims(x, ctx, type, litTypeName); 82 } 83 } 84 85 private char[] calcClassName(JArrayType type) { 86 String leafName = type.getLeafType().getJsniSignatureName(); 87 leafName = leafName.replace('/', '.'); 88 int leafLength = leafName.length(); 89 int nDims = type.getDims(); 90 char[] className = new char[leafLength + nDims]; 91 for (int i = 0; i < nDims; ++i) { 92 className[i] = '['; 93 } 94 95 leafName.getChars(0, leafLength, className, nDims); 96 return className; 97 } 98 99 private void processDims(JNewArray x, Context ctx, JArrayType arrayType, 100 JLiteral litTypeName) { 101 JMethodCall call = new JMethodCall(program, x.getSourceInfo(), null, 103 initDims, arrayType); 104 JsonArray typeIdList = new JsonArray(program); 105 JsonArray queryIdList = new JsonArray(program); 106 JsonArray dimList = new JsonArray(program); 107 JType leafType = arrayType.getLeafType(); 108 int outstandingDims = arrayType.getDims(); 109 for (int i = 0; i < x.dims.size(); ++i) { 110 JExpression dim = (JExpression) x.dims.get(i); 111 if (dim instanceof JAbsentArrayDimension) { 112 break; 113 } 114 115 126 JArrayType cur = program.getTypeArray(leafType, outstandingDims--); 127 JLiteral typeIdLit = program.getLiteralInt(program.getTypeId(cur)); 128 typeIdList.exprs.add(typeIdLit); 129 JLiteral queryIdLit = program.getLiteralInt(tryGetQueryId(cur)); 130 queryIdList.exprs.add(queryIdLit); 131 dimList.exprs.add(dim); 132 } 133 JType targetType = leafType; 134 if (outstandingDims > 0) { 135 targetType = program.getTypeArray(targetType, outstandingDims); 136 } 137 138 call.getArgs().add(litTypeName); 139 call.getArgs().add(typeIdList); 140 call.getArgs().add(queryIdList); 141 call.getArgs().add(dimList); 142 call.getArgs().add(targetType.getDefaultValue()); 143 ctx.replaceMe(call); 144 } 145 146 private void processInitializers(JNewArray x, Context ctx, 147 JArrayType arrayType, JLiteral litTypeName) { 148 JMethodCall call = new JMethodCall(program, x.getSourceInfo(), null, 150 initValues, arrayType); 151 JLiteral typeIdLit = program.getLiteralInt(program.getTypeId(arrayType)); 152 JLiteral queryIdLit = program.getLiteralInt(tryGetQueryId(arrayType)); 153 JsonArray initList = new JsonArray(program); 154 for (int i = 0; i < x.initializers.size(); ++i) { 155 initList.exprs.add(x.initializers.get(i)); 156 } 157 call.getArgs().add(litTypeName); 158 call.getArgs().add(typeIdLit); 159 call.getArgs().add(queryIdLit); 160 call.getArgs().add(initList); 161 ctx.replaceMe(call); 162 } 163 164 private int tryGetQueryId(JArrayType type) { 165 JType elementType = type.getElementType(); 166 int leafTypeId = -1; 167 if (elementType instanceof JReferenceType) { 168 leafTypeId = program.getQueryId((JReferenceType) elementType); 169 } 170 return leafTypeId; 171 } 172 } 173 174 public static void exec(JProgram program) { 175 new ArrayNormalizer(program).execImpl(); 176 } 177 178 private final JMethod initDims; 179 private final JMethod initValues; 180 private final JProgram program; 181 private final JMethod setCheckMethod; 182 183 private ArrayNormalizer(JProgram program) { 184 this.program = program; 185 setCheckMethod = program.getSpecialMethod("Array.setCheck"); 186 initDims = program.getSpecialMethod("Array.initDims"); 187 initValues = program.getSpecialMethod("Array.initValues"); 188 } 189 190 private void execImpl() { 191 ArrayVisitor visitor = new ArrayVisitor(); 192 visitor.accept(program); 193 } 194 195 } 196 | Popular Tags |