1 15 16 package javassist.expr; 17 18 import javassist.*; 19 import javassist.bytecode.*; 20 import javassist.compiler.*; 21 import javassist.compiler.ast.ASTList; 22 23 29 public class NewArray extends Expr { 30 int opcode; 31 32 protected NewArray(int pos, CodeIterator i, CtClass declaring, 33 MethodInfo m, int op) { 34 super(pos, i, declaring, m); 35 opcode = op; 36 } 37 38 42 public CtBehavior where() { return super.where(); } 43 44 50 public int getLineNumber() { 51 return super.getLineNumber(); 52 } 53 54 59 public String getFileName() { 60 return super.getFileName(); 61 } 62 63 69 public CtClass[] mayThrow() { 70 return super.mayThrow(); 71 } 72 73 79 public CtClass getComponentType() throws NotFoundException { 80 if (opcode == Opcode.NEWARRAY) { 81 int atype = iterator.byteAt(currentPos + 1); 82 return getPrimitiveType(atype); 83 } 84 else if (opcode == Opcode.ANEWARRAY 85 || opcode == Opcode.MULTIANEWARRAY) { 86 int index = iterator.u16bitAt(currentPos + 1); 87 String desc = getConstPool().getClassInfo(index); 88 int dim = Descriptor.arrayDimension(desc); 89 desc = Descriptor.toArrayComponent(desc, dim); 90 return Descriptor.toCtClass(desc, thisClass.getClassPool()); 91 } 92 else 93 throw new RuntimeException ("bad opcode: " + opcode); 94 } 95 96 CtClass getPrimitiveType(int atype) { 97 switch (atype) { 98 case Opcode.T_BOOLEAN : 99 return CtClass.booleanType; 100 case Opcode.T_CHAR : 101 return CtClass.charType; 102 case Opcode.T_FLOAT : 103 return CtClass.floatType; 104 case Opcode.T_DOUBLE : 105 return CtClass.doubleType; 106 case Opcode.T_BYTE : 107 return CtClass.byteType; 108 case Opcode.T_SHORT : 109 return CtClass.shortType; 110 case Opcode.T_INT : 111 return CtClass.intType; 112 case Opcode.T_LONG : 113 return CtClass.longType; 114 default : 115 throw new RuntimeException ("bad atype: " + atype); 116 } 117 } 118 119 122 public int getDimension() { 123 if (opcode == Opcode.NEWARRAY) 124 return 1; 125 else if (opcode == Opcode.ANEWARRAY 126 || opcode == Opcode.MULTIANEWARRAY) { 127 int index = iterator.u16bitAt(currentPos + 1); 128 String desc = getConstPool().getClassInfo(index); 129 return Descriptor.arrayDimension(desc) 130 + (opcode == Opcode.ANEWARRAY ? 1 : 0); 131 } 132 else 133 throw new RuntimeException ("bad opcode: " + opcode); 134 } 135 136 141 public int getCreatedDimensions() { 142 if (opcode == Opcode.MULTIANEWARRAY) 143 return iterator.byteAt(currentPos + 3); 144 else 145 return 1; 146 } 147 148 158 public void replace(String statement) throws CannotCompileException { 159 try { 160 replace2(statement); 161 } 162 catch (CompileError e) { throw new CannotCompileException(e); } 163 catch (NotFoundException e) { throw new CannotCompileException(e); } 164 catch (BadBytecode e) { 165 throw new CannotCompileException("broken method"); 166 } 167 } 168 169 private void replace2(String statement) 170 throws CompileError, NotFoundException, BadBytecode, 171 CannotCompileException 172 { 173 ConstPool constPool = getConstPool(); 174 int pos = currentPos; 175 CtClass retType; 176 int codeLength; 177 int index = 0; 178 int dim = 1; 179 String desc; 180 if (opcode == Opcode.NEWARRAY) { 181 index = iterator.byteAt(currentPos + 1); CtPrimitiveType cpt = (CtPrimitiveType)getPrimitiveType(index); 183 desc = "[" + cpt.getDescriptor(); 184 codeLength = 2; 185 } 186 else if (opcode == Opcode.ANEWARRAY) { 187 index = iterator.u16bitAt(pos + 1); 188 desc = constPool.getClassInfo(index); 189 if (desc.startsWith("[")) 190 desc = "[" + desc; 191 else 192 desc = "[L" + desc + ";"; 193 194 codeLength = 3; 195 } 196 else if (opcode == Opcode.MULTIANEWARRAY) { 197 index = iterator.u16bitAt(currentPos + 1); 198 desc = constPool.getClassInfo(index); 199 dim = iterator.byteAt(currentPos + 3); 200 codeLength = 4; 201 } 202 else 203 throw new RuntimeException ("bad opcode: " + opcode); 204 205 retType = Descriptor.toCtClass(desc, thisClass.getClassPool()); 206 207 Javac jc = new Javac(thisClass); 208 CodeAttribute ca = iterator.get(); 209 210 CtClass[] params = new CtClass[dim]; 211 for (int i = 0; i < dim; ++i) 212 params[i] = CtClass.intType; 213 214 int paramVar = ca.getMaxLocals(); 215 jc.recordParams(javaLangObject, params, 216 true, paramVar, withinStatic()); 217 218 220 checkResultValue(retType, statement); 221 int retVar = jc.recordReturnType(retType, true); 222 jc.recordProceed(new ProceedForArray(retType, opcode, index, dim)); 223 224 Bytecode bytecode = jc.getBytecode(); 225 storeStack(params, true, paramVar, bytecode); 226 jc.recordLocalVariables(ca, pos); 227 228 bytecode.addOpcode(ACONST_NULL); bytecode.addAstore(retVar); 230 231 jc.compileStmnt(statement); 232 bytecode.addAload(retVar); 233 234 replace0(pos, bytecode, codeLength); 235 } 236 237 239 static class ProceedForArray implements ProceedHandler { 240 CtClass arrayType; 241 int opcode; 242 int index, dimension; 243 244 ProceedForArray(CtClass type, int op, int i, int dim) { 245 arrayType = type; 246 opcode = op; 247 index = i; 248 dimension = dim; 249 } 250 251 public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args) 252 throws CompileError 253 { 254 int num = gen.getMethodArgsLength(args); 255 if (num != dimension) 256 throw new CompileError(Javac.proceedName 257 + "() with a wrong number of parameters"); 258 259 gen.atMethodArgs(args, new int[num], 260 new int[num], new String [num]); 261 bytecode.addOpcode(opcode); 262 if (opcode == Opcode.ANEWARRAY) 263 bytecode.addIndex(index); 264 else if (opcode == Opcode.NEWARRAY) 265 bytecode.add(index); 266 else { 267 bytecode.addIndex(index); 268 bytecode.add(dimension); 269 bytecode.growStack(1 - dimension); 270 } 271 272 gen.setType(arrayType); 273 } 274 275 public void setReturnType(JvstTypeChecker c, ASTList args) 276 throws CompileError 277 { 278 c.setType(arrayType); 279 } 280 } 281 } 282 | Popular Tags |