You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Expr.java 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  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. package javassist.expr;
  16. import javassist.*;
  17. import javassist.bytecode.*;
  18. import javassist.compiler.*;
  19. import java.util.LinkedList;
  20. import java.util.Iterator;
  21. /**
  22. * Caller-side expression.
  23. */
  24. abstract class Expr implements Opcode {
  25. int currentPos;
  26. CodeIterator iterator;
  27. CtClass thisClass;
  28. MethodInfo thisMethod;
  29. boolean edited;
  30. int maxLocals, maxStack;
  31. static final String javaLangObject = "java.lang.Object";
  32. Expr(int pos, CodeIterator i, CtClass declaring, MethodInfo m) {
  33. currentPos = pos;
  34. iterator = i;
  35. thisClass = declaring;
  36. thisMethod = m;
  37. }
  38. final ConstPool getConstPool() {
  39. return thisMethod.getConstPool();
  40. }
  41. final boolean edited() { return edited; }
  42. final int locals() { return maxLocals; }
  43. final int stack() { return maxStack; }
  44. /**
  45. * Returns true if this method is static.
  46. */
  47. final boolean withinStatic() {
  48. return (thisMethod.getAccessFlags() & AccessFlag.STATIC) != 0;
  49. }
  50. /**
  51. * Returns the constructor or method containing the expression.
  52. */
  53. public CtBehavior where() {
  54. MethodInfo mi = thisMethod;
  55. CtBehavior[] cb = thisClass.getDeclaredBehaviors();
  56. for (int i = cb.length - 1; i >= 0; --i)
  57. if (cb[i].getMethodInfo() == mi)
  58. return cb[i];
  59. throw new RuntimeException("fatal: not found");
  60. }
  61. /**
  62. * Returns the list of exceptions that the expression may throw.
  63. * This list includes both the exceptions that the try-catch statements
  64. * including the expression can catch and the exceptions that
  65. * the throws declaration allows the method to throw.
  66. */
  67. public CtClass[] mayThrow() {
  68. ClassPool pool = thisClass.getClassPool();
  69. ConstPool cp = thisMethod.getConstPool();
  70. LinkedList list = new LinkedList();
  71. try {
  72. CodeAttribute ca = thisMethod.getCodeAttribute();
  73. ExceptionTable et = ca.getExceptionTable();
  74. int pos = currentPos;
  75. int n = et.size();
  76. for (int i = 0; i < n; ++i)
  77. if (et.startPc(i) <= pos && pos < et.endPc(i)) {
  78. int t = et.catchType(i);
  79. if (t > 0)
  80. try {
  81. addClass(list, pool.get(cp.getClassInfo(t)));
  82. }
  83. catch (NotFoundException e) {}
  84. }
  85. }
  86. catch (NullPointerException e) {}
  87. ExceptionsAttribute ea = thisMethod.getExceptionsAttribute();
  88. if (ea != null) {
  89. String[] exceptions = ea.getExceptions();
  90. if (exceptions != null) {
  91. int n = exceptions.length;
  92. for (int i = 0; i < n; ++i)
  93. try {
  94. addClass(list, pool.get(exceptions[i]));
  95. }
  96. catch (NotFoundException e) {}
  97. }
  98. }
  99. return (CtClass[])list.toArray(new CtClass[list.size()]);
  100. }
  101. private static void addClass(LinkedList list, CtClass c) {
  102. Iterator it = list.iterator();
  103. while (it.hasNext())
  104. if (it.next() == c)
  105. return;
  106. list.add(c);
  107. }
  108. /**
  109. * Returns the line number of the source line containing the
  110. * expression.
  111. *
  112. * @return -1 if this information is not available.
  113. */
  114. public int getLineNumber() {
  115. return thisMethod.getLineNumber(currentPos);
  116. }
  117. /**
  118. * Returns the source file containing the expression.
  119. *
  120. * @return null if this information is not available.
  121. */
  122. public String getFileName() {
  123. ClassFile cf = thisClass.getClassFile2();
  124. if (cf == null)
  125. return null;
  126. else
  127. return cf.getSourceFile();
  128. }
  129. static final boolean checkResultValue(CtClass retType, String prog)
  130. throws CannotCompileException
  131. {
  132. /* Is $_ included in the source code?
  133. */
  134. boolean hasIt = (prog.indexOf(Javac.resultVarName) >= 0);
  135. if (!hasIt && retType != CtClass.voidType)
  136. throw new CannotCompileException(
  137. "the resulting value is not stored in "
  138. + Javac.resultVarName);
  139. return hasIt;
  140. }
  141. /* If isStaticCall is true, null is assigned to $0. So $0 must
  142. * be declared by calling Javac.recordParams().
  143. *
  144. * After executing this method, the current stack depth might
  145. * be less than 0.
  146. */
  147. static final void storeStack(CtClass[] params, boolean isStaticCall,
  148. int regno, Bytecode bytecode) {
  149. storeStack0(0, params.length, params, regno + 1, bytecode);
  150. if (isStaticCall)
  151. bytecode.addOpcode(ACONST_NULL);
  152. bytecode.addAstore(regno);
  153. }
  154. private static void storeStack0(int i, int n, CtClass[] params,
  155. int regno, Bytecode bytecode) {
  156. if (i >= n)
  157. return;
  158. else {
  159. CtClass c = params[i];
  160. int size;
  161. if (c instanceof CtPrimitiveType)
  162. size = ((CtPrimitiveType)c).getDataSize();
  163. else
  164. size = 1;
  165. storeStack0(i + 1, n, params, regno + size, bytecode);
  166. bytecode.addStore(regno, c);
  167. }
  168. }
  169. protected void replace0(int pos, Bytecode bytecode, int size)
  170. throws BadBytecode
  171. {
  172. byte[] code = bytecode.get();
  173. edited = true;
  174. int gap = code.length - size;
  175. for (int i = 0; i < size; ++i)
  176. iterator.writeByte(NOP, pos + i);
  177. if (gap > 0)
  178. iterator.insertGap(pos, gap);
  179. iterator.write(code, pos);
  180. iterator.insert(bytecode.getExceptionTable(), pos);
  181. maxLocals = bytecode.getMaxLocals();
  182. maxStack = bytecode.getMaxStack();
  183. }
  184. }