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 26 public class NewExpr extends Expr { 27 String newTypeName; 28 int newPos; 29 30 33 protected NewExpr(int pos, CodeIterator i, CtClass declaring, 34 MethodInfo m, String type, int np) { 35 super(pos, i, declaring, m); 36 newTypeName = type; 37 newPos = np; 38 } 39 40 private int getNameAndType(ConstPool cp) { 41 String cname; 42 int pos = currentPos; 43 int c = iterator.byteAt(pos); 44 int index = iterator.u16bitAt(pos + 1); 45 46 if (c == INVOKEINTERFACE) 47 return cp.getInterfaceMethodrefNameAndType(index); 48 else 49 return cp.getMethodrefNameAndType(index); 50 } 51 52 56 public CtBehavior where() { return super.where(); } 57 58 64 public int getLineNumber() { 65 return super.getLineNumber(); 66 } 67 68 73 public String getFileName() { 74 return super.getFileName(); 75 } 76 77 80 private CtClass getCtClass() throws NotFoundException { 81 return thisClass.getClassPool().get(newTypeName); 82 } 83 84 87 public String getClassName() { 88 return newTypeName; 89 } 90 91 94 public CtConstructor getConstructor() throws NotFoundException { 95 ConstPool cp = getConstPool(); 96 int index = iterator.u16bitAt(currentPos + 1); 97 String desc = cp.getMethodrefType(index); 98 return getCtClass().getConstructor(desc); 99 } 100 101 107 public CtClass[] mayThrow() { 108 return super.mayThrow(); 109 } 110 111 121 122 private int canReplace() throws CannotCompileException { 123 int op = iterator.byteAt(newPos + 3); 124 if (op == Opcode.DUP) 125 return 4; 126 else if (op == Opcode.DUP_X1 127 && iterator.byteAt(newPos + 4) == Opcode.SWAP) 128 return 5; 129 else 130 throw new CannotCompileException( 131 "sorry, cannot edit NEW followed by no DUP"); 132 } 133 134 142 public void replace(String statement) throws CannotCompileException { 143 final int bytecodeSize = 3; 144 int pos = newPos; 145 146 int newIndex = iterator.u16bitAt(pos + 1); 147 148 150 int end = pos + canReplace(); 151 for (int i = pos; i < end; ++i) 152 iterator.writeByte(NOP, i); 153 154 ConstPool constPool = getConstPool(); 155 pos = currentPos; 156 int methodIndex = iterator.u16bitAt(pos + 1); 158 String signature = constPool.getMethodrefType(methodIndex); 159 160 Javac jc = new Javac(thisClass); 161 ClassPool cp = thisClass.getClassPool(); 162 CodeAttribute ca = iterator.get(); 163 try { 164 CtClass[] params = Descriptor.getParameterTypes(signature, cp); 165 CtClass newType = cp.get(newTypeName); 166 int paramVar = ca.getMaxLocals(); 167 jc.recordParams(newTypeName, params, 168 true, paramVar, withinStatic()); 169 int retVar = jc.recordReturnType(newType, true); 170 jc.recordProceed(new ProceedForNew(newType, newIndex, 171 methodIndex)); 172 173 175 checkResultValue(newType, statement); 176 177 Bytecode bytecode = jc.getBytecode(); 178 storeStack(params, true, paramVar, bytecode); 179 jc.recordLocalVariables(ca, pos); 180 181 bytecode.addConstZero(newType); 182 bytecode.addStore(retVar, newType); 184 jc.compileStmnt(statement); 185 bytecode.addAload(retVar); 186 187 replace0(pos, bytecode, bytecodeSize); 188 } 189 catch (CompileError e) { throw new CannotCompileException(e); } 190 catch (NotFoundException e) { throw new CannotCompileException(e); } 191 catch (BadBytecode e) { 192 throw new CannotCompileException("broken method"); 193 } 194 } 195 196 static class ProceedForNew implements ProceedHandler { 197 CtClass newType; 198 int newIndex, methodIndex; 199 200 ProceedForNew(CtClass nt, int ni, int mi) { 201 newType = nt; 202 newIndex = ni; 203 methodIndex = mi; 204 } 205 206 public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args) 207 throws CompileError 208 { 209 bytecode.addOpcode(NEW); 210 bytecode.addIndex(newIndex); 211 bytecode.addOpcode(DUP); 212 gen.atMethodCallCore(newType, MethodInfo.nameInit, args, 213 false, true, -1, null); 214 gen.setType(newType); 215 } 216 217 public void setReturnType(JvstTypeChecker c, ASTList args) 218 throws CompileError 219 { 220 c.atMethodCallCore(newType, MethodInfo.nameInit, args); 221 c.setType(newType); 222 } 223 } 224 } 225 | Popular Tags |