diff options
Diffstat (limited to 'src/main/javassist/expr/Expr.java')
-rw-r--r-- | src/main/javassist/expr/Expr.java | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/src/main/javassist/expr/Expr.java b/src/main/javassist/expr/Expr.java new file mode 100644 index 00000000..d88d7939 --- /dev/null +++ b/src/main/javassist/expr/Expr.java @@ -0,0 +1,223 @@ +/* + * This file is part of the Javassist toolkit. + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * either http://www.mozilla.org/MPL/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is Javassist. + * + * The Initial Developer of the Original Code is Shigeru Chiba. Portions + * created by Shigeru Chiba are Copyright (C) 1999-2003 Shigeru Chiba. + * All Rights Reserved. + * + * Contributor(s): + * + * The development of this software is supported in part by the PRESTO + * program (Sakigake Kenkyu 21) of Japan Science and Technology Corporation. + */ + +package javassist.expr; + +import javassist.*; +import javassist.bytecode.*; +import javassist.compiler.*; +import java.util.LinkedList; +import java.util.Iterator; + +/** + * Caller-side expression. + */ +abstract class Expr implements Opcode { + int currentPos; + CodeIterator iterator; + CtClass thisClass; + MethodInfo thisMethod; + + boolean edited; + int maxLocals, maxStack; + + static final String javaLangObject = "java.lang.Object"; + + Expr(int pos, CodeIterator i, CtClass declaring, MethodInfo m) { + currentPos = pos; + iterator = i; + thisClass = declaring; + thisMethod = m; + } + + final ConstPool getConstPool() { + return thisMethod.getConstPool(); + } + + final boolean edited() { return edited; } + + final int locals() { return maxLocals; } + + final int stack() { return maxStack; } + + /** + * Returns true if this method is static. + */ + final boolean withinStatic() { + return (thisMethod.getAccessFlags() & AccessFlag.STATIC) != 0; + } + + /** + * Returns the constructor or method containing the expression. + */ + public CtBehavior where() { + MethodInfo mi = thisMethod; + CtBehavior[] cb = thisClass.getDeclaredBehaviors(); + for (int i = cb.length - 1; i >= 0; --i) + if (cb[i].getMethodInfo() == mi) + return cb[i]; + + throw new RuntimeException("fatal: not found"); + } + + /** + * Returns the list of exceptions that the expression may throw. + * This list includes both the exceptions that the try-catch statements + * including the expression can catch and the exceptions that + * the throws declaration allows the method to throw. + */ + public CtClass[] mayThrow() { + ClassPool pool = thisClass.getClassPool(); + ConstPool cp = thisMethod.getConstPool(); + LinkedList list = new LinkedList(); + try { + CodeAttribute ca = thisMethod.getCodeAttribute(); + ExceptionTable et = ca.getExceptionTable(); + int pos = currentPos; + int n = et.size(); + for (int i = 0; i < n; ++i) + if (et.startPc(i) <= pos && pos < et.endPc(i)) { + int t = et.catchType(i); + if (t > 0) + try { + addClass(list, pool.get(cp.getClassInfo(t))); + } + catch (NotFoundException e) {} + } + } + catch (NullPointerException e) {} + + ExceptionsAttribute ea = thisMethod.getExceptionsAttribute(); + if (ea != null) { + String[] exceptions = ea.getExceptions(); + if (exceptions != null) { + int n = exceptions.length; + for (int i = 0; i < n; ++i) + try { + addClass(list, pool.get(exceptions[i])); + } + catch (NotFoundException e) {} + } + } + + return (CtClass[])list.toArray(new CtClass[list.size()]); + } + + private static void addClass(LinkedList list, CtClass c) { + Iterator it = list.iterator(); + while (it.hasNext()) + if (it.next() == c) + return; + + list.add(c); + } + + /** + * Returns the line number of the source line containing the + * expression. + * + * @return -1 if this information is not available. + */ + public int getLineNumber() { + return thisMethod.getLineNumber(currentPos); + } + + /** + * Returns the source file containing the expression. + * + * @return null if this information is not available. + */ + public String getFileName() { + ClassFile cf = thisClass.getClassFile2(); + if (cf == null) + return null; + else + return cf.getSourceFile(); + } + + static final boolean checkResultValue(CtClass retType, String prog) + throws CannotCompileException + { + /* Is $_ included in the source code? + */ + boolean hasIt = (prog.indexOf(Javac.resultVarName) >= 0); + if (!hasIt && retType != CtClass.voidType) + throw new CannotCompileException( + "the resulting value is not stored in " + + Javac.resultVarName); + + return hasIt; + } + + /* If isStaticCall is true, null is assigned to $0. So $0 must + * be declared by calling Javac.recordParams(). + * + * After executing this method, the current stack depth might + * be less than 0. + */ + static final void storeStack(CtClass[] params, boolean isStaticCall, + int regno, Bytecode bytecode) { + storeStack0(0, params.length, params, regno + 1, bytecode); + if (isStaticCall) + bytecode.addOpcode(ACONST_NULL); + + bytecode.addAstore(regno); + } + + private static void storeStack0(int i, int n, CtClass[] params, + int regno, Bytecode bytecode) { + if (i >= n) + return; + else { + CtClass c = params[i]; + int size; + if (c instanceof CtPrimitiveType) + size = ((CtPrimitiveType)c).getDataSize(); + else + size = 1; + + storeStack0(i + 1, n, params, regno + size, bytecode); + bytecode.addStore(regno, c); + } + } + + protected void replace0(int pos, Bytecode bytecode, int size) + throws BadBytecode + { + byte[] code = bytecode.get(); + edited = true; + int gap = code.length - size; + if (gap > 0) + iterator.insertGap(pos, gap); + else + for (int i = 0; i < size; ++i) + iterator.writeByte(NOP, pos + i); + + iterator.write(code, pos); + iterator.insert(bytecode.getExceptionTable(), pos); + maxLocals = bytecode.getMaxLocals(); + maxStack = bytecode.getMaxStack(); + } +} |