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.

Instanceof.java 6.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /*
  2. * Javassist, a Java-bytecode translator toolkit.
  3. * Copyright (C) 1999- 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. * or the Apache License Version 2.0.
  10. *
  11. * Software distributed under the License is distributed on an "AS IS" basis,
  12. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  13. * for the specific language governing rights and limitations under the
  14. * License.
  15. */
  16. package javassist.expr;
  17. import javassist.CannotCompileException;
  18. import javassist.ClassPool;
  19. import javassist.CtBehavior;
  20. import javassist.CtClass;
  21. import javassist.NotFoundException;
  22. import javassist.bytecode.BadBytecode;
  23. import javassist.bytecode.Bytecode;
  24. import javassist.bytecode.CodeAttribute;
  25. import javassist.bytecode.CodeIterator;
  26. import javassist.bytecode.ConstPool;
  27. import javassist.bytecode.MethodInfo;
  28. import javassist.bytecode.Opcode;
  29. import javassist.compiler.CompileError;
  30. import javassist.compiler.Javac;
  31. import javassist.compiler.JvstCodeGen;
  32. import javassist.compiler.JvstTypeChecker;
  33. import javassist.compiler.ProceedHandler;
  34. import javassist.compiler.ast.ASTList;
  35. /**
  36. * Instanceof operator.
  37. */
  38. public class Instanceof extends Expr {
  39. /**
  40. * Undocumented constructor. Do not use; internal-use only.
  41. */
  42. protected Instanceof(int pos, CodeIterator i, CtClass declaring,
  43. MethodInfo m) {
  44. super(pos, i, declaring, m);
  45. }
  46. /**
  47. * Returns the method or constructor containing the instanceof
  48. * expression represented by this object.
  49. */
  50. @Override
  51. public CtBehavior where() { return super.where(); }
  52. /**
  53. * Returns the line number of the source line containing the
  54. * instanceof expression.
  55. *
  56. * @return -1 if this information is not available.
  57. */
  58. @Override
  59. public int getLineNumber() {
  60. return super.getLineNumber();
  61. }
  62. /**
  63. * Returns the source file containing the
  64. * instanceof expression.
  65. *
  66. * @return null if this information is not available.
  67. */
  68. @Override
  69. public String getFileName() {
  70. return super.getFileName();
  71. }
  72. /**
  73. * Returns the <code>CtClass</code> object representing
  74. * the type name on the right hand side
  75. * of the instanceof operator.
  76. */
  77. public CtClass getType() throws NotFoundException {
  78. ConstPool cp = getConstPool();
  79. int pos = currentPos;
  80. int index = iterator.u16bitAt(pos + 1);
  81. String name = cp.getClassInfo(index);
  82. return thisClass.getClassPool().getCtClass(name);
  83. }
  84. /**
  85. * Returns the list of exceptions that the expression may throw.
  86. * This list includes both the exceptions that the try-catch statements
  87. * including the expression can catch and the exceptions that
  88. * the throws declaration allows the method to throw.
  89. */
  90. @Override
  91. public CtClass[] mayThrow() {
  92. return super.mayThrow();
  93. }
  94. /**
  95. * Replaces the instanceof operator with the bytecode derived from
  96. * the given source text.
  97. *
  98. * <p>$0 is available but the value is <code>null</code>.
  99. *
  100. * @param statement a Java statement except try-catch.
  101. */
  102. @Override
  103. public void replace(String statement) throws CannotCompileException {
  104. thisClass.getClassFile(); // to call checkModify().
  105. @SuppressWarnings("unused")
  106. ConstPool constPool = getConstPool();
  107. int pos = currentPos;
  108. int index = iterator.u16bitAt(pos + 1);
  109. Javac jc = new Javac(thisClass);
  110. ClassPool cp = thisClass.getClassPool();
  111. CodeAttribute ca = iterator.get();
  112. try {
  113. CtClass[] params
  114. = new CtClass[] { cp.get(javaLangObject) };
  115. CtClass retType = CtClass.booleanType;
  116. int paramVar = ca.getMaxLocals();
  117. jc.recordParams(javaLangObject, params, true, paramVar,
  118. withinStatic());
  119. int retVar = jc.recordReturnType(retType, true);
  120. jc.recordProceed(new ProceedForInstanceof(index));
  121. // because $type is not the return type...
  122. jc.recordType(getType());
  123. /* Is $_ included in the source code?
  124. */
  125. checkResultValue(retType, statement);
  126. Bytecode bytecode = jc.getBytecode();
  127. storeStack(params, true, paramVar, bytecode);
  128. jc.recordLocalVariables(ca, pos);
  129. bytecode.addConstZero(retType);
  130. bytecode.addStore(retVar, retType); // initialize $_
  131. jc.compileStmnt(statement);
  132. bytecode.addLoad(retVar, retType);
  133. replace0(pos, bytecode, 3);
  134. }
  135. catch (CompileError e) { throw new CannotCompileException(e); }
  136. catch (NotFoundException e) { throw new CannotCompileException(e); }
  137. catch (BadBytecode e) {
  138. throw new CannotCompileException("broken method");
  139. }
  140. }
  141. /* boolean $proceed(Object obj)
  142. */
  143. static class ProceedForInstanceof implements ProceedHandler {
  144. int index;
  145. ProceedForInstanceof(int i) {
  146. index = i;
  147. }
  148. @Override
  149. public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args, int lineNumber)
  150. throws CompileError
  151. {
  152. if (gen.getMethodArgsLength(args) != 1)
  153. throw new CompileError(Javac.proceedName
  154. + "() cannot take more than one parameter "
  155. + "for instanceof", lineNumber);
  156. gen.atMethodArgs(args, new int[1], new int[1], new String[1]);
  157. bytecode.addOpcode(Opcode.INSTANCEOF);
  158. bytecode.addIndex(index);
  159. gen.setType(CtClass.booleanType, lineNumber);
  160. }
  161. @Override
  162. public void setReturnType(JvstTypeChecker c, ASTList args, int lineNumber)
  163. throws CompileError
  164. {
  165. c.atMethodArgs(args, new int[1], new int[1], new String[1]);
  166. c.setType(CtClass.booleanType, lineNumber);
  167. }
  168. }
  169. }