1 package serp.bytecode; 2 3 import java.io.*; 4 import java.util.*; 5 6 import serp.bytecode.visitor.*; 7 8 /*** 9 * The <code>newarray</code> instruction, which is used to create new 10 * arrays of primitive types. 11 * 12 * @author Abe White 13 */ 14 public class NewArrayInstruction extends TypedInstruction { 15 private static final Class[][] _mappings = new Class[][] { 16 { void.class, int.class }, 17 { Object.class, int.class }, 18 }; 19 private int _code = -1; 20 21 NewArrayInstruction(Code owner) { 22 super(owner, Constants.NEWARRAY); 23 } 24 25 int getLength() { 26 return super.getLength() + 1; 27 } 28 29 public String getTypeName() { 30 switch (getTypeCode()) { 31 case Constants.ARRAY_BOOLEAN: 32 return boolean.class.getName(); 33 case Constants.ARRAY_CHAR: 34 return char.class.getName(); 35 case Constants.ARRAY_FLOAT: 36 return float.class.getName(); 37 case Constants.ARRAY_DOUBLE: 38 return double.class.getName(); 39 case Constants.ARRAY_BYTE: 40 return byte.class.getName(); 41 case Constants.ARRAY_SHORT: 42 return short.class.getName(); 43 case Constants.ARRAY_INT: 44 return int.class.getName(); 45 case Constants.ARRAY_LONG: 46 return long.class.getName(); 47 default: 48 return null; 49 } 50 } 51 52 public TypedInstruction setType(String type) { 53 type = mapType(type, _mappings, true); 54 if (type == null) 55 return setTypeCode(-1); 56 57 switch (type.charAt(0)) { 58 case 'b': 59 if (boolean.class.getName().equals(type)) 60 return setTypeCode(Constants.ARRAY_BOOLEAN); 61 return setTypeCode(Constants.ARRAY_BYTE); 62 case 'c': 63 return setTypeCode(Constants.ARRAY_CHAR); 64 case 'f': 65 return setTypeCode(Constants.ARRAY_FLOAT); 66 case 'd': 67 return setTypeCode(Constants.ARRAY_DOUBLE); 68 case 's': 69 return setTypeCode(Constants.ARRAY_SHORT); 70 case 'i': 71 return setTypeCode(Constants.ARRAY_INT); 72 case 'l': 73 return setTypeCode(Constants.ARRAY_LONG); 74 default: 75 throw new IllegalStateException(); 76 } 77 } 78 79 /*** 80 * Return the array code used in the lowlevel bytecode, or -1 if unset. 81 */ 82 public int getTypeCode() { 83 return _code; 84 } 85 86 /*** 87 * Set the array code used in the lowlevel bytecode. 88 * 89 * @return this instruction, for method chaining 90 */ 91 public NewArrayInstruction setTypeCode(int code) { 92 _code = code; 93 return this; 94 } 95 96 /*** 97 * NewArray instructions are equal if the array type is the same, 98 * of if the array type of either is unset. 99 */ 100 public boolean equalsInstruction(Instruction other) { 101 if (this == other) 102 return true; 103 if (!(other instanceof NewArrayInstruction)) 104 return false; 105 106 NewArrayInstruction ins = (NewArrayInstruction) other; 107 int code = getTypeCode(); 108 int otherCode = ins.getTypeCode(); 109 return code == -1 || otherCode == -1 || code == otherCode; 110 } 111 112 public void acceptVisit(BCVisitor visit) { 113 visit.enterNewArrayInstruction(this); 114 visit.exitNewArrayInstruction(this); 115 } 116 117 void read(Instruction orig) { 118 super.read(orig); 119 _code = ((NewArrayInstruction) orig).getTypeCode(); 120 } 121 122 void read(DataInput in) throws IOException { 123 super.read(in); 124 _code = in.readUnsignedByte(); 125 } 126 127 void write(DataOutput out) throws IOException { 128 super.write(out); 129 out.writeByte(_code); 130 } 131 }