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.

BCELFactory.java 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. package org.aspectj.apache.bcel.verifier.util;
  2. import java.io.PrintWriter;
  3. import java.util.ArrayList;
  4. import java.util.HashMap;
  5. import java.util.Iterator;
  6. import org.aspectj.apache.bcel.Constants;
  7. import org.aspectj.apache.bcel.classfile.ConstantPool;
  8. import org.aspectj.apache.bcel.classfile.Utility;
  9. import org.aspectj.apache.bcel.generic.BranchHandle;
  10. import org.aspectj.apache.bcel.generic.CodeExceptionGen;
  11. import org.aspectj.apache.bcel.generic.FieldInstruction;
  12. import org.aspectj.apache.bcel.generic.IINC;
  13. import org.aspectj.apache.bcel.generic.Instruction;
  14. import org.aspectj.apache.bcel.generic.InstructionBranch;
  15. import org.aspectj.apache.bcel.generic.InstructionByte;
  16. import org.aspectj.apache.bcel.generic.InstructionCP;
  17. import org.aspectj.apache.bcel.generic.InstructionConstants;
  18. import org.aspectj.apache.bcel.generic.InstructionHandle;
  19. import org.aspectj.apache.bcel.generic.InstructionSelect;
  20. import org.aspectj.apache.bcel.generic.InvokeInstruction;
  21. import org.aspectj.apache.bcel.generic.MULTIANEWARRAY;
  22. import org.aspectj.apache.bcel.generic.MethodGen;
  23. import org.aspectj.apache.bcel.generic.ObjectType;
  24. import org.aspectj.apache.bcel.generic.RET;
  25. import org.aspectj.apache.bcel.generic.Type;
  26. import org.aspectj.apache.bcel.verifier.InstructionWalker;
  27. /* ====================================================================
  28. * The Apache Software License, Version 1.1
  29. *
  30. * Copyright (c) 2002 The Apache Software Foundation. All rights
  31. * reserved.
  32. *
  33. * Redistribution and use in source and binary forms, with or without
  34. * modification, are permitted provided that the following conditions
  35. * are met:
  36. *
  37. * 1. Redistributions of source code must retain the above copyright
  38. * notice, this list of conditions and the following disclaimer.
  39. *
  40. * 2. Redistributions in binary form must reproduce the above copyright
  41. * notice, this list of conditions and the following disclaimer in
  42. * the documentation and/or other materials provided with the
  43. * distribution.
  44. *
  45. * 3. The end-user documentation included with the redistribution,
  46. * if any, must include the following acknowledgment:
  47. * "This product includes software developed by the
  48. * Apache Software Foundation (https://www.apache.org/)."
  49. * Alternately, this acknowledgment may appear in the software itself,
  50. * if and wherever such third-party acknowledgments normally appear.
  51. *
  52. * 4. The names "Apache" and "Apache Software Foundation" and
  53. * "Apache BCEL" must not be used to endorse or promote products
  54. * derived from this software without prior written permission. For
  55. * written permission, please contact apache@apache.org.
  56. *
  57. * 5. Products derived from this software may not be called "Apache",
  58. * "Apache BCEL", nor may "Apache" appear in their name, without
  59. * prior written permission of the Apache Software Foundation.
  60. *
  61. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  62. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  63. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  64. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  65. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  66. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  67. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  68. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  69. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  70. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  71. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  72. * SUCH DAMAGE.
  73. * ====================================================================
  74. *
  75. * This software consists of voluntary contributions made by many
  76. * individuals on behalf of the Apache Software Foundation. For more
  77. * information on the Apache Software Foundation, please see
  78. * <https://www.apache.org/>.
  79. */
  80. /**
  81. * Factory creates il.append() statements, and sets instruction targets. A helper class for BCELifier.
  82. *
  83. * @see BCELifier
  84. * @version $Id: BCELFactory.java,v 1.6 2009/09/14 20:29:10 aclement Exp $
  85. * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
  86. */
  87. class BCELFactory extends org.aspectj.apache.bcel.verifier.EmptyInstVisitor {
  88. private final MethodGen _mg;
  89. private final PrintWriter _out;
  90. private final ConstantPool _cp;
  91. BCELFactory(MethodGen mg, PrintWriter out) {
  92. _mg = mg;
  93. _cp = mg.getConstantPool();
  94. _out = out;
  95. }
  96. private final HashMap<Instruction, InstructionHandle> branch_map = new HashMap<Instruction, InstructionHandle>(); // Map<Instruction,
  97. // InstructionHandle>
  98. public void start() {
  99. if (!_mg.isAbstract() && !_mg.isNative()) {
  100. for (InstructionHandle ih = _mg.getInstructionList().getStart(); ih != null; ih = ih.getNext()) {
  101. Instruction i = ih.getInstruction();
  102. if (i instanceof InstructionBranch) {
  103. branch_map.put(i, ih); // memorize container
  104. }
  105. if (ih.hasTargeters()) {
  106. if (i instanceof InstructionBranch) {
  107. _out.println(" InstructionHandle ih_" + ih.getPosition() + ";");
  108. } else {
  109. _out.print(" InstructionHandle ih_" + ih.getPosition() + " = ");
  110. }
  111. } else {
  112. _out.print(" ");
  113. }
  114. if (!visitInstruction(i)) {
  115. InstructionWalker.accept(i, this);
  116. }
  117. }
  118. updateBranchTargets();
  119. updateExceptionHandlers();
  120. }
  121. }
  122. private boolean visitInstruction(Instruction i) {
  123. short opcode = i.getOpcode();
  124. if (InstructionConstants.INSTRUCTIONS[opcode] != null && !i.isConstantInstruction() && !i.isReturnInstruction()) { // Handled
  125. // below
  126. _out.println("il.append(InstructionConstants." + i.getName().toUpperCase() + ");");
  127. return true;
  128. }
  129. return false;
  130. }
  131. public void visitLocalVariableInstruction(Instruction i) {
  132. short opcode = i.getOpcode();
  133. Type type = i.getType(_cp);
  134. if (opcode == Constants.IINC) {
  135. _out.println("il.append(new IINC(" + i.getIndex() + ", " + ((IINC) i).getIncrement() + "));");
  136. } else {
  137. String kind = opcode < Constants.ISTORE ? "Load" : "Store";
  138. _out.println("il.append(_factory.create" + kind + "(" + BCELifier.printType(type) + ", " + i.getIndex() + "));");
  139. }
  140. }
  141. @Override
  142. public void visitArrayInstruction(Instruction i) {
  143. short opcode = i.getOpcode();
  144. Type type = i.getType(_cp);
  145. String kind = opcode < Constants.IASTORE ? "Load" : "Store";
  146. _out.println("il.append(_factory.createArray" + kind + "(" + BCELifier.printType(type) + "));");
  147. }
  148. public void visitFieldInstruction(FieldInstruction i) {
  149. short opcode = i.getOpcode();
  150. String class_name = i.getClassName(_cp);
  151. String field_name = i.getFieldName(_cp);
  152. Type type = i.getFieldType(_cp);
  153. _out.println("il.append(_factory.createFieldAccess(\"" + class_name + "\", \"" + field_name + "\", "
  154. + BCELifier.printType(type) + ", " + "Constants." + Constants.OPCODE_NAMES[opcode].toUpperCase() + "));");
  155. }
  156. @Override
  157. public void visitInvokeInstruction(InvokeInstruction i) {
  158. short opcode = i.getOpcode();
  159. String class_name = i.getClassName(_cp);
  160. String method_name = i.getMethodName(_cp);
  161. Type type = i.getReturnType(_cp);
  162. Type[] arg_types = i.getArgumentTypes(_cp);
  163. _out.println("il.append(_factory.createInvoke(\"" + class_name + "\", \"" + method_name + "\", "
  164. + BCELifier.printType(type) + ", " + BCELifier.printArgumentTypes(arg_types) + ", " + "Constants."
  165. + Constants.OPCODE_NAMES[opcode].toUpperCase() + "));");
  166. }
  167. @Override
  168. public void visitAllocationInstruction(Instruction i) {
  169. Type type;
  170. if (i.isConstantPoolInstruction()) {
  171. type = ((InstructionCP) i).getType(_cp);
  172. } else {
  173. type = ((InstructionByte) i).getType();
  174. }
  175. short opcode = i.getOpcode();
  176. int dim = 1;
  177. switch (opcode) {
  178. case Constants.NEW:
  179. _out.println("il.append(_factory.createNew(\"" + ((ObjectType) type).getClassName() + "\"));");
  180. break;
  181. case Constants.MULTIANEWARRAY:
  182. dim = ((MULTIANEWARRAY) i).getDimensions();
  183. case Constants.ANEWARRAY:
  184. case Constants.NEWARRAY:
  185. _out.println("il.append(_factory.createNewArray(" + BCELifier.printType(type) + ", (short) " + dim + "));");
  186. break;
  187. default:
  188. throw new RuntimeException("Oops: " + opcode);
  189. }
  190. }
  191. private void createConstant(Object value) {
  192. String embed = value.toString();
  193. if (value instanceof String) {
  194. embed = '"' + Utility.convertString(value.toString()) + '"';
  195. } else if (value instanceof Character) {
  196. embed = "(char)0x" + Integer.toHexString(((Character) value).charValue());
  197. }
  198. _out.println("il.append(new PUSH(_cp, " + embed + "));");
  199. }
  200. @Override
  201. public void visitLDC(Instruction i) {
  202. createConstant(i.getValue(_cp));
  203. }
  204. @Override
  205. public void visitLDC2_W(Instruction i) {
  206. createConstant(i.getValue(_cp));
  207. }
  208. @Override
  209. public void visitConstantPushInstruction(Instruction i) {
  210. createConstant(i.getValue());
  211. }
  212. @Override
  213. public void visitINSTANCEOF(Instruction i) {
  214. Type type = i.getType(_cp);
  215. _out.println("il.append(new INSTANCEOF(_cp.addClass(" + BCELifier.printType(type) + ")));");
  216. }
  217. @Override
  218. public void visitCHECKCAST(Instruction i) {
  219. Type type = i.getType(_cp);
  220. _out.println("il.append(_factory.createCheckCast(" + BCELifier.printType(type) + "));");
  221. }
  222. @Override
  223. public void visitReturnInstruction(Instruction i) {
  224. Type type = i.getType(_cp);
  225. _out.println("il.append(_factory.createReturn(" + BCELifier.printType(type) + "));");
  226. }
  227. // Memorize BranchInstructions that need an update
  228. private final ArrayList<InstructionBranch> branches = new ArrayList<InstructionBranch>();
  229. @Override
  230. public void visitBranchInstruction(InstructionBranch bi) {
  231. BranchHandle bh = (BranchHandle) branch_map.get(bi);
  232. int pos = bh.getPosition();
  233. String name = bi.getName() + "_" + pos;
  234. if (bi instanceof InstructionSelect) {
  235. InstructionSelect s = (InstructionSelect) bi;
  236. branches.add(bi);
  237. StringBuffer args = new StringBuffer("new int[] { ");
  238. int[] matchs = s.getMatchs();
  239. for (int i = 0; i < matchs.length; i++) {
  240. args.append(matchs[i]);
  241. if (i < matchs.length - 1) {
  242. args.append(", ");
  243. }
  244. }
  245. args.append(" }");
  246. _out.print(" Select " + name + " = new " + bi.getName().toUpperCase() + "(" + args + ", new InstructionHandle[] { ");
  247. for (int i = 0; i < matchs.length; i++) {
  248. _out.print("null");
  249. if (i < matchs.length - 1) {
  250. _out.print(", ");
  251. }
  252. }
  253. _out.println(");");
  254. } else {
  255. int t_pos = bh.getTarget().getPosition();
  256. String target;
  257. if (pos > t_pos) {
  258. target = "ih_" + t_pos;
  259. } else {
  260. branches.add(bi);
  261. target = "null";
  262. }
  263. _out.println(" BranchInstruction " + name + " = _factory.createBranchInstruction(" + "Constants."
  264. + bi.getName().toUpperCase() + ", " + target + ");");
  265. }
  266. if (bh.hasTargeters()) {
  267. _out.println(" ih_" + pos + " = il.append(" + name + ");");
  268. } else {
  269. _out.println(" il.append(" + name + ");");
  270. }
  271. }
  272. @Override
  273. public void visitRET(RET i) {
  274. _out.println("il.append(new RET(" + i.getIndex() + ")));");
  275. }
  276. private void updateBranchTargets() {
  277. for (Iterator<InstructionBranch> i = branches.iterator(); i.hasNext();) {
  278. InstructionBranch bi = i.next();
  279. BranchHandle bh = (BranchHandle) branch_map.get(bi);
  280. int pos = bh.getPosition();
  281. String name = bi.getName() + "_" + pos;
  282. int t_pos = bh.getTarget().getPosition();
  283. _out.println(" " + name + ".setTarget(ih_" + t_pos + ");");
  284. if (bi instanceof InstructionSelect) {
  285. InstructionHandle[] ihs = ((InstructionSelect) bi).getTargets();
  286. for (int j = 0; j < ihs.length; j++) {
  287. t_pos = ihs[j].getPosition();
  288. _out.println(" " + name + ".setTarget(" + j + ", ih_" + t_pos + ");");
  289. }
  290. }
  291. }
  292. }
  293. private void updateExceptionHandlers() {
  294. CodeExceptionGen[] handlers = _mg.getExceptionHandlers();
  295. for (int i = 0; i < handlers.length; i++) {
  296. CodeExceptionGen h = handlers[i];
  297. String type = h.getCatchType() == null ? "null" : BCELifier.printType(h.getCatchType());
  298. _out.println(" method.addExceptionHandler(" + "ih_" + h.getStartPC().getPosition() + ", " + "ih_"
  299. + h.getEndPC().getPosition() + ", " + "ih_" + h.getHandlerPC().getPosition() + ", " + type + ");");
  300. }
  301. }
  302. }