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 }