/Users/lyon/j4p/src/javassist/expr/Expr.java
|
1 /*
2 * Javassist, a Java-bytecode translator toolkit.
3 * Copyright (C) 1999-2003 Shigeru Chiba. All Rights Reserved.
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. Alternatively, the contents of this file may be used under
8 * the terms of the GNU Lesser General Public License Version 2.1 or later.
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 */
15
16 package javassist.expr;
17
18 import javassist.*;
19 import javassist.bytecode.*;
20 import javassist.compiler.*;
21
22 import java.util.LinkedList;
23 import java.util.Iterator;
24
25 /**
26 * Expression.
27 */
28 public abstract class Expr implements Opcode {
29 int currentPos;
30 CodeIterator iterator;
31 CtClass thisClass;
32 MethodInfo thisMethod;
33
34 boolean edited;
35 int maxLocals, maxStack;
36
37 static final String javaLangObject = "java.lang.Object";
38
39 /**
40 * Undocumented constructor. Do not use; internal-use only.
41 */
42 protected Expr(int pos, CodeIterator i, CtClass declaring, MethodInfo m) {
43 currentPos = pos;
44 iterator = i;
45 thisClass = declaring;
46 thisMethod = m;
47 }
48
49 final ConstPool getConstPool() {
50 return thisMethod.getConstPool();
51 }
52
53 final boolean edited() {
54 return edited;
55 }
56
57 final int locals() {
58 return maxLocals;
59 }
60
61 final int stack() {
62 return maxStack;
63 }
64
65 /**
66 * Returns true if this method is static.
67 */
68 final boolean withinStatic() {
69 return (thisMethod.getAccessFlags() & AccessFlag.STATIC) != 0;
70 }
71
72 /**
73 * Returns the constructor or method containing the expression.
74 */
75 public CtBehavior where() {
76 MethodInfo mi = thisMethod;
77 CtBehavior[] cb = thisClass.getDeclaredBehaviors();
78 for (int i = cb.length - 1; i >= 0; --i)
79 if (cb[i].getMethodInfo() == mi)
80 return cb[i];
81
82 throw new RuntimeException("fatal: not found");
83 }
84
85 /**
86 * Returns the list of exceptions that the expression may throw.
87 * This list includes both the exceptions that the try-catch statements
88 * including the expression can catch and the exceptions that
89 * the throws declaration allows the method to throw.
90 */
91 public CtClass[] mayThrow() {
92 ClassPool pool = thisClass.getClassPool();
93 ConstPool cp = thisMethod.getConstPool();
94 LinkedList list = new LinkedList();
95 try {
96 CodeAttribute ca = thisMethod.getCodeAttribute();
97 ExceptionTable et = ca.getExceptionTable();
98 int pos = currentPos;
99 int n = et.size();
100 for (int i = 0; i < n; ++i)
101 if (et.startPc(i) <= pos && pos < et.endPc(i)) {
102 int t = et.catchType(i);
103 if (t > 0)
104 try {
105 addClass(list, pool.get(cp.getClassInfo(t)));
106 } catch (NotFoundException e) {
107 }
108 }
109 } catch (NullPointerException e) {
110 }
111
112 ExceptionsAttribute ea = thisMethod.getExceptionsAttribute();
113 if (ea != null) {
114 String[] exceptions = ea.getExceptions();
115 if (exceptions != null) {
116 int n = exceptions.length;
117 for (int i = 0; i < n; ++i)
118 try {
119 addClass(list, pool.get(exceptions[i]));
120 } catch (NotFoundException e) {
121 }
122 }
123 }
124
125 return (CtClass[]) list.toArray(new CtClass[list.size()]);
126 }
127
128 private static void addClass(LinkedList list, CtClass c) {
129 Iterator it = list.iterator();
130 while (it.hasNext())
131 if (it.next() == c)
132 return;
133
134 list.add(c);
135 }
136
137 /**
138 * Returns the index of the bytecode corresponding to the
139 * expression.
140 * It is the index into the byte array containing the Java bytecode
141 * that implements the method.
142 */
143 public int indexOfBytecode() {
144 return currentPos;
145 }
146
147 /**
148 * Returns the line number of the source line containing the
149 * expression.
150 *
151 * @return -1 if this information is not available.
152 */
153 public int getLineNumber() {
154 return thisMethod.getLineNumber(currentPos);
155 }
156
157 /**
158 * Returns the source file containing the expression.
159 *
160 * @return null if this information is not available.
161 */
162 public String getFileName() {
163 ClassFile cf = thisClass.getClassFile2();
164 if (cf == null)
165 return null;
166 else
167 return cf.getSourceFile();
168 }
169
170 static final boolean checkResultValue(CtClass retType, String prog)
171 throws CannotCompileException {
172 /* Is $_ included in the source code?
173 */
174 boolean hasIt = (prog.indexOf(Javac.resultVarName) >= 0);
175 if (!hasIt && retType != CtClass.voidType)
176 throw new CannotCompileException(
177 "the resulting value is not stored in "
178 + Javac.resultVarName);
179
180 return hasIt;
181 }
182
183 /* If isStaticCall is true, null is assigned to $0. So $0 must
184 * be declared by calling Javac.recordParams().
185 *
186 * After executing this method, the current stack depth might
187 * be less than 0.
188 */
189 static final void storeStack(CtClass[] params, boolean isStaticCall,
190 int regno, Bytecode bytecode) {
191 storeStack0(0, params.length, params, regno + 1, bytecode);
192 if (isStaticCall)
193 bytecode.addOpcode(ACONST_NULL);
194
195 bytecode.addAstore(regno);
196 }
197
198 private static void storeStack0(int i, int n, CtClass[] params,
199 int regno, Bytecode bytecode) {
200 if (i >= n)
201 return;
202 else {
203 CtClass c = params[i];
204 int size;
205 if (c instanceof CtPrimitiveType)
206 size = ((CtPrimitiveType) c).getDataSize();
207 else
208 size = 1;
209
210 storeStack0(i + 1, n, params, regno + size, bytecode);
211 bytecode.addStore(regno, c);
212 }
213 }
214
215 protected void replace0(int pos, Bytecode bytecode, int size)
216 throws BadBytecode {
217 byte[] code = bytecode.get();
218 edited = true;
219 int gap = code.length - size;
220 for (int i = 0; i < size; ++i)
221 iterator.writeByte(NOP, pos + i);
222
223 if (gap > 0)
224 iterator.insertGap(pos, gap);
225
226 iterator.write(code, pos);
227 iterator.insert(bytecode.getExceptionTable(), pos);
228 maxLocals = bytecode.getMaxLocals();
229 maxStack = bytecode.getMaxStack();
230 }
231 }
232