001 package serp.bytecode;
002
003 import java.io.*;
004
005 import serp.bytecode.lowlevel.*;
006 import serp.bytecode.visitor.*;
007
008 /**
009 * An instruction that takes as an argument a class to operate
010 * on. Examples include <code>anewarray, checkcast, instance, anew</code>, etc.
011 *
012 * @author Abe White
013 */
014 public class ClassInstruction extends TypedInstruction {
015 private int _index = 0;
016
017 ClassInstruction(Code owner, int opcode) {
018 super(owner, opcode);
019 }
020
021 public int getStackChange() {
022 if (getOpcode() == Constants.NEW)
023 return 1;
024 return 0;
025 }
026
027 int getLength() {
028 return super.getLength() + 2;
029 }
030
031 /**
032 * Return the {@link ConstantPool} index of the
033 * {@link ClassEntry} describing the class for this instruction.
034 */
035 public int getTypeIndex() {
036 return _index;
037 }
038
039 /**
040 * Set the {@link ConstantPool} index of the
041 * {@link ClassEntry} describing the class for this instruction.
042 *
043 * @return this instruction, for method chaining
044 */
045 public ClassInstruction setTypeIndex(int index) {
046 _index = index;
047 return this;
048 }
049
050 public String getTypeName() {
051 if (_index == 0)
052 return null;
053
054 ClassEntry entry = (ClassEntry) getPool().getEntry(_index);
055 return getProject().getNameCache().getExternalForm(entry.
056 getNameEntry().getValue(), false);
057 }
058
059 public TypedInstruction setType(String type) {
060 if (type == null)
061 _index = 0;
062 else {
063 type = getProject().getNameCache().getInternalForm(type, false);
064 _index = getPool().findClassEntry(type, true);
065 }
066 return this;
067 }
068
069 /**
070 * ClassInstructions are equal if the type they reference is the same or
071 * unset and if their opcodes are equal.
072 */
073 public boolean equalsInstruction(Instruction other) {
074 if (other == this)
075 return true;
076 if (!super.equalsInstruction(other))
077 return false;
078
079 String type = getTypeName();
080 String otherType = ((ClassInstruction) other).getTypeName();
081 return (type == null) || (otherType == null) || type.equals(otherType);
082 }
083
084 public void acceptVisit(BCVisitor visit) {
085 visit.enterClassInstruction(this);
086 visit.exitClassInstruction(this);
087 }
088
089 void read(Instruction other) {
090 super.read(other);
091 setType(((ClassInstruction) other).getTypeName());
092 }
093
094 void read(DataInput in) throws IOException {
095 super.read(in);
096 _index = in.readUnsignedShort();
097 }
098
099 void write(DataOutput out) throws IOException {
100 super.write(out);
101 out.writeShort(_index);
102 }
103 }