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.

Instruction.java 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. package org.aspectj.apache.bcel.generic;
  2. /* ====================================================================
  3. * The Apache Software License, Version 1.1
  4. *
  5. * Copyright (c) 2001 The Apache Software Foundation. All rights
  6. * reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. *
  20. * 3. The end-user documentation included with the redistribution,
  21. * if any, must include the following acknowledgment:
  22. * "This product includes software developed by the
  23. * Apache Software Foundation (http://www.apache.org/)."
  24. * Alternately, this acknowledgment may appear in the software itself,
  25. * if and wherever such third-party acknowledgments normally appear.
  26. *
  27. * 4. The names "Apache" and "Apache Software Foundation" and
  28. * "Apache BCEL" must not be used to endorse or promote products
  29. * derived from this software without prior written permission. For
  30. * written permission, please contact apache@apache.org.
  31. *
  32. * 5. Products derived from this software may not be called "Apache",
  33. * "Apache BCEL", nor may "Apache" appear in their name, without
  34. * prior written permission of the Apache Software Foundation.
  35. *
  36. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  37. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  38. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  39. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  40. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  41. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  42. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  43. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  44. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  45. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  46. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  47. * SUCH DAMAGE.
  48. * ====================================================================
  49. *
  50. * This software consists of voluntary contributions made by many
  51. * individuals on behalf of the Apache Software Foundation. For more
  52. * information on the Apache Software Foundation, please see
  53. * <http://www.apache.org/>.
  54. */
  55. import java.io.DataOutputStream;
  56. import java.io.IOException;
  57. import java.io.Serializable;
  58. import org.aspectj.apache.bcel.Constants;
  59. import org.aspectj.apache.bcel.classfile.ConstantPool;
  60. import org.aspectj.apache.bcel.util.ByteSequence;
  61. import com.sun.org.apache.bcel.internal.generic.BranchInstruction;
  62. /**
  63. * Abstract super class for all Java byte codes.
  64. *
  65. * @version $Id: Instruction.java,v 1.7 2008/08/28 00:06:23 aclement Exp $
  66. * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
  67. */
  68. public class Instruction implements Cloneable, Serializable, Constants {
  69. public short opcode = -1;
  70. private Instruction() {
  71. }
  72. public Instruction(short opcode) {
  73. this.opcode = opcode;
  74. }
  75. public void dump(DataOutputStream out) throws IOException {
  76. out.writeByte(opcode);
  77. }
  78. public String getName() {
  79. return Constants.OPCODE_NAMES[opcode];
  80. }
  81. /**
  82. * Use with caution, since `BranchInstruction's have a `target' reference which is not copied correctly (only basic types are).
  83. * This also applies for `Select' instructions with their multiple branch targets.
  84. *
  85. * @see BranchInstruction
  86. * @return (shallow) copy of an instruction
  87. */
  88. final public Instruction copy() {
  89. if (InstructionConstants.INSTRUCTIONS[opcode] != null) { // immutable instructions do not need copying
  90. return this;
  91. } else {
  92. Instruction i = null;
  93. try {// OPTIMIZE is clone the right thing to do here? it is horrible
  94. i = (Instruction) clone();
  95. } catch (CloneNotSupportedException e) {
  96. System.err.println(e);
  97. }
  98. return i;
  99. }
  100. }
  101. /**
  102. * Read an instruction from (byte code) input stream and return the appropiate object.
  103. *
  104. * @param file file to read from
  105. * @return instruction object being read
  106. */
  107. public static final Instruction readInstruction(ByteSequence bytes) throws IOException {
  108. boolean wide = false;
  109. short opcode = (short) bytes.readUnsignedByte();
  110. Instruction obj = null;
  111. if (opcode == Constants.WIDE) {
  112. wide = true;
  113. opcode = (short) bytes.readUnsignedByte();
  114. }
  115. Instruction constantInstruction = InstructionConstants.INSTRUCTIONS[opcode];
  116. if (constantInstruction != null) {
  117. return constantInstruction;
  118. }
  119. try {
  120. switch (opcode) {
  121. case Constants.BIPUSH:
  122. obj = new InstructionByte(Constants.BIPUSH, bytes.readByte());
  123. break;
  124. case Constants.SIPUSH:
  125. obj = new InstructionShort(Constants.SIPUSH, bytes.readShort());
  126. break;
  127. case Constants.LDC:
  128. obj = new InstructionCP(Constants.LDC, bytes.readUnsignedByte());
  129. break;
  130. case Constants.LDC_W:
  131. case Constants.LDC2_W:
  132. obj = new InstructionCP(opcode, bytes.readUnsignedShort());
  133. break;
  134. case Constants.ILOAD:
  135. case Constants.LLOAD:
  136. case Constants.FLOAD:
  137. case Constants.DLOAD:
  138. case Constants.ALOAD:
  139. case Constants.ISTORE:
  140. case Constants.LSTORE:
  141. case Constants.FSTORE:
  142. case Constants.DSTORE:
  143. case Constants.ASTORE:
  144. obj = new InstructionLV(opcode, wide ? bytes.readUnsignedShort() : bytes.readUnsignedByte());
  145. break;
  146. case Constants.IINC:
  147. obj = new IINC(wide ? bytes.readUnsignedShort() : bytes.readUnsignedByte(), wide ? bytes.readShort() : bytes
  148. .readByte(), wide);
  149. break;
  150. case Constants.IFNULL:
  151. case Constants.IFNONNULL:
  152. case Constants.IFEQ:
  153. case Constants.IFNE:
  154. case Constants.IFLT:
  155. case Constants.IFGE:
  156. case Constants.IFGT:
  157. case Constants.IFLE:
  158. case Constants.IF_ICMPEQ:
  159. case Constants.IF_ICMPNE:
  160. case Constants.IF_ICMPLT:
  161. case Constants.IF_ICMPGE:
  162. case Constants.IF_ICMPGT:
  163. case Constants.IF_ICMPLE:
  164. case Constants.IF_ACMPEQ:
  165. case Constants.IF_ACMPNE:
  166. case Constants.GOTO:
  167. case Constants.JSR:
  168. obj = new InstructionBranch(opcode, bytes.readShort());
  169. break;
  170. case Constants.GOTO_W:
  171. case Constants.JSR_W:
  172. obj = new InstructionBranch(opcode, bytes.readInt());
  173. break;
  174. case Constants.TABLESWITCH:
  175. obj = new TABLESWITCH(bytes);
  176. break;
  177. case Constants.LOOKUPSWITCH:
  178. obj = new LOOKUPSWITCH(bytes);
  179. break;
  180. case Constants.RET:
  181. obj = new RET(wide ? bytes.readUnsignedShort() : bytes.readUnsignedByte(), wide);
  182. break;
  183. case Constants.NEW:
  184. obj = new InstructionCP(Constants.NEW, bytes.readUnsignedShort());
  185. break;
  186. case Constants.GETSTATIC:
  187. case Constants.PUTSTATIC:
  188. case Constants.GETFIELD:
  189. case Constants.PUTFIELD:
  190. obj = new FieldInstruction(opcode, bytes.readUnsignedShort());
  191. break;
  192. case Constants.INVOKEVIRTUAL:
  193. case Constants.INVOKESPECIAL:
  194. case Constants.INVOKESTATIC:
  195. obj = new InvokeInstruction(opcode, bytes.readUnsignedShort());
  196. break;
  197. case Constants.INVOKEINTERFACE:
  198. obj = new INVOKEINTERFACE(bytes.readUnsignedShort(), bytes.readUnsignedByte(), bytes.readByte());
  199. break;
  200. case Constants.NEWARRAY:
  201. obj = new InstructionByte(Constants.NEWARRAY, bytes.readByte());
  202. break;
  203. case Constants.ANEWARRAY:
  204. case Constants.CHECKCAST:
  205. obj = new InstructionCP(opcode, bytes.readUnsignedShort());
  206. break;
  207. case Constants.INSTANCEOF:
  208. obj = new InstructionCP(Constants.INSTANCEOF, bytes.readUnsignedShort());
  209. break;
  210. case Constants.MULTIANEWARRAY:
  211. obj = new MULTIANEWARRAY(bytes.readUnsignedShort(), bytes.readByte());
  212. break;
  213. default:
  214. throw new ClassGenException("Illegal opcode detected");
  215. }
  216. } catch (ClassGenException e) {
  217. throw e;
  218. } catch (Exception e) {
  219. throw new ClassGenException(e.toString());
  220. }
  221. return obj;
  222. }
  223. /**
  224. * @return Number of words consumed from stack by this instruction, or Constants.UNPREDICTABLE, if this can not be computed
  225. * statically
  226. */
  227. public int consumeStack(ConstantPool cpg) {
  228. return Constants.CONSUME_STACK[opcode];
  229. }
  230. /**
  231. * @return Number of words produced onto stack by this instruction, or Constants.UNPREDICTABLE, if this can not be computed
  232. * statically
  233. */
  234. public int produceStack(ConstantPool cpg) {
  235. return Constants.stackEntriesProduced[opcode];
  236. }
  237. public short getOpcode() {
  238. return opcode;
  239. }
  240. public int getLength() {
  241. // if it is zero, it should have been provided by an overriding implementation of getLength()
  242. int len = Constants.iLen[opcode];
  243. if (len == 0) {
  244. throw new IllegalStateException("Length not right for " + getName().toUpperCase());
  245. }
  246. return len;
  247. }
  248. /** Some instructions may be reused, so don't do anything by default */
  249. void dispose() {
  250. }
  251. public boolean equals(Object that) {
  252. if (!(that instanceof Instruction)) {
  253. return false;
  254. }
  255. Instruction i1 = this;
  256. Instruction i2 = (Instruction) that;
  257. if (i1.opcode == i2.opcode) {
  258. if (i1.isConstantInstruction()) {
  259. return i1.getValue().equals(i2.getValue());
  260. } else if (i1.isIndexedInstruction()) {
  261. return i1.getIndex() == i2.getIndex();
  262. } else if (i1.opcode == Constants.NEWARRAY) {
  263. return ((InstructionByte) i1).getTypecode() == ((InstructionByte) i2).getTypecode();
  264. } else {
  265. return true;
  266. }
  267. }
  268. return false;
  269. }
  270. public int hashCode() {
  271. int result = 17 + opcode * 37;
  272. if (isConstantInstruction()) {
  273. result = 37 * getValue().hashCode() + result;
  274. } else if (isIndexedInstruction()) {
  275. result = 37 * getIndex() + result;
  276. } else if (opcode == Constants.NEWARRAY) {
  277. result = 37 * ((InstructionByte) this).getTypecode() + result;
  278. }
  279. return result;
  280. }
  281. public Type getType() {
  282. return getType(null);
  283. }
  284. public Type getType(ConstantPool cp) {
  285. // if (types[opcode]==null) throw new RuntimeException(getName()+" is not a typed instruction");
  286. Type t = Constants.types[opcode];
  287. if (t != null) {
  288. return t;
  289. }
  290. throw new RuntimeException("Do not know type for instruction " + getName() + "(" + opcode + ")");
  291. }
  292. public Number getValue() {
  293. if ((instFlags[opcode] & CONSTANT_INST) == 0) {
  294. throw new RuntimeException(getName() + " is not a constant instruction");
  295. }
  296. switch (opcode) {
  297. case ICONST_M1:
  298. case ICONST_0:
  299. case ICONST_1:
  300. case ICONST_2:
  301. case ICONST_3:
  302. case ICONST_4:
  303. case ICONST_5:
  304. return new Integer(opcode - ICONST_0);
  305. default:
  306. throw new IllegalStateException("Not implemented yet for " + getName());
  307. }
  308. }
  309. public int getIndex() {
  310. return -1;
  311. }
  312. public void setIndex(int i) {
  313. throw new IllegalStateException("Shouldnt be asking " + getName().toUpperCase());
  314. }
  315. public Object getValue(ConstantPool cpg) {
  316. throw new IllegalStateException("Shouldnt be asking " + getName().toUpperCase());
  317. }
  318. public boolean isLoadInstruction() {
  319. return (Constants.instFlags[opcode] & LOAD_INST) != 0;
  320. }
  321. public boolean isALOAD() {
  322. return false;
  323. }
  324. public boolean isStoreInstruction() {
  325. return (Constants.instFlags[opcode] & STORE_INST) != 0;
  326. }
  327. public boolean isASTORE() {
  328. return false;
  329. }
  330. public java.lang.Class[] getExceptions() {
  331. // fixme
  332. return Constants.instExcs[opcode];
  333. }
  334. public boolean containsTarget(InstructionHandle ih) {
  335. throw new IllegalStateException("Dont ask!!");
  336. }
  337. public void updateTarget(InstructionHandle old_ih, InstructionHandle new_ih) {
  338. throw new IllegalStateException("Dont ask!!");
  339. }
  340. public boolean isJsrInstruction() {
  341. return (Constants.instFlags[opcode] & JSR_INSTRUCTION) != 0;
  342. }
  343. public boolean isConstantInstruction() {
  344. return (Constants.instFlags[opcode] & CONSTANT_INST) != 0;
  345. }
  346. public boolean isConstantPoolInstruction() {
  347. return (Constants.instFlags[opcode] & CP_INST) != 0;
  348. }
  349. public boolean isStackProducer() {
  350. return Constants.stackEntriesProduced[opcode] != 0;
  351. // return ((Constants.instFlags[opcode]&STACK_PRODUCER)!=0);
  352. }
  353. public boolean isStackConsumer() {
  354. return Constants.CONSUME_STACK[opcode] != 0;
  355. // return ((Constants.instFlags[opcode]&STACK_CONSUMER)!=0);
  356. }
  357. public boolean isIndexedInstruction() {
  358. return (Constants.instFlags[opcode] & INDEXED) != 0;
  359. }
  360. public boolean isArrayCreationInstruction() {
  361. return opcode == NEWARRAY || opcode == ANEWARRAY || opcode == MULTIANEWARRAY;
  362. }
  363. public ObjectType getLoadClassType(ConstantPool cpg) {
  364. if ((Constants.instFlags[opcode] & Constants.LOADCLASS_INST) == 0) {
  365. throw new IllegalStateException("This opcode " + opcode + " does not have the property "
  366. + Long.toHexString(Constants.LOADCLASS_INST));
  367. }
  368. Type t = getType(cpg);
  369. if (t instanceof ArrayType) {
  370. t = ((ArrayType) t).getBasicType();
  371. }
  372. return t instanceof ObjectType ? (ObjectType) t : null;
  373. }
  374. public boolean isReturnInstruction() {
  375. return (Constants.instFlags[opcode] & RET_INST) != 0;
  376. }
  377. public boolean isGoto() {
  378. return opcode == GOTO || opcode == GOTO_W;
  379. }
  380. public boolean isLocalVariableInstruction() {
  381. return (Constants.instFlags[opcode] & LV_INST) != 0;
  382. }
  383. /**
  384. * Long output format: 'name of opcode' "[" 'opcode number' "]" "(" 'length of instruction' ")"
  385. */
  386. public String toString(boolean verbose) {
  387. if (verbose) {
  388. StringBuffer sb = new StringBuffer();
  389. sb.append(getName()).append("[").append(opcode).append("](size").append(Constants.iLen[opcode]).append(")");
  390. return sb.toString();
  391. } else {
  392. return getName();
  393. }
  394. }
  395. public String toString() {
  396. return toString(true);
  397. }
  398. }