Expr.java revision 69e17611504376e4d4603925f8528dfc890fd2c6
169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/* 269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Javassist, a Java-bytecode translator toolkit. 369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved. 469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The contents of this file are subject to the Mozilla Public License Version 669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1.1 (the "License"); you may not use this file except in compliance with 769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the License. Alternatively, the contents of this file may be used under 869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the terms of the GNU Lesser General Public License Version 2.1 or later. 969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Software distributed under the License is distributed on an "AS IS" basis, 1169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 1269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * for the specific language governing rights and limitations under the 1369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * License. 1469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 1569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpackage javassist.expr; 1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CannotCompileException; 1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.ClassPool; 2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CtBehavior; 2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CtClass; 2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CtConstructor; 2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CtPrimitiveType; 2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.NotFoundException; 2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.AccessFlag; 2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.BadBytecode; 2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.Bytecode; 2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.ClassFile; 2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.CodeAttribute; 3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.CodeIterator; 3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.ConstPool; 3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.ExceptionTable; 3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.ExceptionsAttribute; 3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.MethodInfo; 3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.Opcode; 3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.compiler.Javac; 3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.util.Iterator; 3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.util.LinkedList; 4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/** 4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Expression. 4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic abstract class Expr implements Opcode { 4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int currentPos; 4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CodeIterator iterator; 4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass thisClass; 4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal MethodInfo thisMethod; 4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal boolean edited; 5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int maxLocals, maxStack; 5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal static final String javaLangObject = "java.lang.Object"; 5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Undocumented constructor. Do not use; internal-use only. 5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected Expr(int pos, CodeIterator i, CtClass declaring, MethodInfo m) { 5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal currentPos = pos; 5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal iterator = i; 6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal thisClass = declaring; 6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal thisMethod = m; 6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns the class that declares the method enclosing 6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * this expression. 6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @since 3.7 6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public CtClass getEnclosingClass() { return thisClass; } 7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected final ConstPool getConstPool() { 7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return thisMethod.getConstPool(); 7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected final boolean edited() { 7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return edited; 7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected final int locals() { 8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return maxLocals; 8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected final int stack() { 8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return maxStack; 8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns true if this method is static. 9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected final boolean withinStatic() { 9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return (thisMethod.getAccessFlags() & AccessFlag.STATIC) != 0; 9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns the constructor or method containing the expression. 9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public CtBehavior where() { 9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal MethodInfo mi = thisMethod; 10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtBehavior[] cb = thisClass.getDeclaredBehaviors(); 10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = cb.length - 1; i >= 0; --i) 10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (cb[i].getMethodInfo2() == mi) 10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return cb[i]; 10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtConstructor init = thisClass.getClassInitializer(); 10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (init != null && init.getMethodInfo2() == mi) 10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return init; 10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* getDeclaredBehaviors() returns a list of methods/constructors. 11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Although the list is cached in a CtClass object, it might be 11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * recreated for some reason. Thus, the member name and the signature 11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * must be also checked. 11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = cb.length - 1; i >= 0; --i) { 11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (thisMethod.getName().equals(cb[i].getMethodInfo2().getName()) 11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal && thisMethod.getDescriptor() 11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal .equals(cb[i].getMethodInfo2().getDescriptor())) { 11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return cb[i]; 11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new RuntimeException("fatal: not found"); 12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns the list of exceptions that the expression may throw. This list 12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * includes both the exceptions that the try-catch statements including the 12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * expression can catch and the exceptions that the throws declaration 12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * allows the method to throw. 13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public CtClass[] mayThrow() { 13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ClassPool pool = thisClass.getClassPool(); 13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ConstPool cp = thisMethod.getConstPool(); 13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal LinkedList list = new LinkedList(); 13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CodeAttribute ca = thisMethod.getCodeAttribute(); 13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ExceptionTable et = ca.getExceptionTable(); 13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int pos = currentPos; 13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int n = et.size(); 14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < n; ++i) 14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (et.startPc(i) <= pos && pos < et.endPc(i)) { 14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int t = et.catchType(i); 14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (t > 0) 14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal addClass(list, pool.get(cp.getClassInfo(t))); 14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (NotFoundException e) { 14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (NullPointerException e) { 15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ExceptionsAttribute ea = thisMethod.getExceptionsAttribute(); 15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (ea != null) { 15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String[] exceptions = ea.getExceptions(); 15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (exceptions != null) { 15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int n = exceptions.length; 15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < n; ++i) 16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal addClass(list, pool.get(exceptions[i])); 16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (NotFoundException e) { 16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 16669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 16769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 16869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return (CtClass[])list.toArray(new CtClass[list.size()]); 16969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 17069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 17169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private static void addClass(LinkedList list, CtClass c) { 17269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Iterator it = list.iterator(); 17369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while (it.hasNext()) 17469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (it.next() == c) 17569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return; 17669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 17769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal list.add(c); 17869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 17969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 18069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 18169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns the index of the bytecode corresponding to the expression. It is 18269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the index into the byte array containing the Java bytecode that 18369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * implements the method. 18469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 18569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public int indexOfBytecode() { 18669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return currentPos; 18769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 18869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 18969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 19069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns the line number of the source line containing the expression. 19169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 19269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @return -1 if this information is not available. 19369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 19469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public int getLineNumber() { 19569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return thisMethod.getLineNumber(currentPos); 19669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 19769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 19869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 19969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns the source file containing the expression. 20069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 20169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @return null if this information is not available. 20269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 20369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public String getFileName() { 20469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ClassFile cf = thisClass.getClassFile2(); 20569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (cf == null) 20669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return null; 20769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 20869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return cf.getSourceFile(); 20969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 21069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 21169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal static final boolean checkResultValue(CtClass retType, String prog) 21269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CannotCompileException { 21369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 21469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Is $_ included in the source code? 21569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 21669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal boolean hasIt = (prog.indexOf(Javac.resultVarName) >= 0); 21769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (!hasIt && retType != CtClass.voidType) 21869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CannotCompileException( 21969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal "the resulting value is not stored in " 22069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal + Javac.resultVarName); 22169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 22269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return hasIt; 22369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 22469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 22569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 22669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * If isStaticCall is true, null is assigned to $0. So $0 must be declared 22769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * by calling Javac.recordParams(). 22869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 22969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * After executing this method, the current stack depth might be less than 23069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 0. 23169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 23269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal static final void storeStack(CtClass[] params, boolean isStaticCall, 23369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int regno, Bytecode bytecode) { 23469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal storeStack0(0, params.length, params, regno + 1, bytecode); 23569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (isStaticCall) 23669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal bytecode.addOpcode(ACONST_NULL); 23769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 23869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal bytecode.addAstore(regno); 23969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 24069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 24169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private static void storeStack0(int i, int n, CtClass[] params, int regno, 24269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Bytecode bytecode) { 24369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (i >= n) 24469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return; 24569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 24669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass c = params[i]; 24769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int size; 24869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (c instanceof CtPrimitiveType) 24969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal size = ((CtPrimitiveType)c).getDataSize(); 25069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 25169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal size = 1; 25269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 25369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal storeStack0(i + 1, n, params, regno + size, bytecode); 25469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal bytecode.addStore(regno, c); 25569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 25669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 25769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 25869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // The implementation of replace() should call thisClass.checkModify() 25969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // so that isModify() will return true. Otherwise, thisClass.classfile 26069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // might be released during compilation and the compiler might generate 26169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // bytecode with a wrong copy of ConstPool. 26269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 26369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 26469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Replaces this expression with the bytecode derived from 26569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the given source text. 26669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 26769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param statement a Java statement except try-catch. 26869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 26969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public abstract void replace(String statement) throws CannotCompileException; 27069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 27169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 27269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Replaces this expression with the bytecode derived from 27369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the given source text and <code>ExprEditor</code>. 27469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 27569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param statement a Java statement except try-catch. 27669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param recursive if not null, the substituted bytecode 27769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * is recursively processed by the given 27869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>ExprEditor</code>. 27969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @since 3.1 28069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 28169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void replace(String statement, ExprEditor recursive) 28269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CannotCompileException 28369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 28469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal replace(statement); 28569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (recursive != null) 28669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal runEditor(recursive, iterator); 28769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 28869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 28969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected void replace0(int pos, Bytecode bytecode, int size) 29069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws BadBytecode { 29169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal byte[] code = bytecode.get(); 29269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal edited = true; 29369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int gap = code.length - size; 29469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < size; ++i) 29569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal iterator.writeByte(NOP, pos + i); 29669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 29769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (gap > 0) 29869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal pos = iterator.insertGapAt(pos, gap, false).position; 29969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 30069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal iterator.write(code, pos); 30169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal iterator.insert(bytecode.getExceptionTable(), pos); 30269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal maxLocals = bytecode.getMaxLocals(); 30369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal maxStack = bytecode.getMaxStack(); 30469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 30569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 30669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected void runEditor(ExprEditor ed, CodeIterator oldIterator) 30769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CannotCompileException 30869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 30969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CodeAttribute codeAttr = oldIterator.get(); 31069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int orgLocals = codeAttr.getMaxLocals(); 31169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int orgStack = codeAttr.getMaxStack(); 31269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int newLocals = locals(); 31369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal codeAttr.setMaxStack(stack()); 31469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal codeAttr.setMaxLocals(newLocals); 31569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ExprEditor.LoopContext context 31669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal = new ExprEditor.LoopContext(newLocals); 31769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int size = oldIterator.getCodeLength(); 31869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int endPos = oldIterator.lookAhead(); 31969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal oldIterator.move(currentPos); 32069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (ed.doit(thisClass, thisMethod, context, oldIterator, endPos)) 32169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal edited = true; 32269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 32369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal oldIterator.move(endPos + oldIterator.getCodeLength() - size); 32469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal codeAttr.setMaxLocals(orgLocals); 32569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal codeAttr.setMaxStack(orgStack); 32669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal maxLocals = context.maxLocals; 32769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal maxStack += context.maxStack; 32869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 32969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal} 330