aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/javassist/expr/Expr.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/javassist/expr/Expr.java')
-rw-r--r--src/main/javassist/expr/Expr.java223
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();
+ }
+}