1 cananian 1.1.2.5 // ArrayRef.java, created Sat Mar 27 17:05:07 1999 by duncan 2 cananian 1.1.2.4 // Copyright (C) 1998 C. Scott Ananian <cananian@alumni.princeton.edu> 3 cananian 1.1.2.4 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 duncan 1.1.2.1 package harpoon.Interpret.Tree; 5 duncan 1.1.2.1 6 duncan 1.1.2.1 // ArrayRef.java, created Mon Dec 28 03:02:39 1998 by cananian 7 duncan 1.1.2.1 8 duncan 1.1.2.1 import harpoon.ClassFile.HClass; 9 duncan 1.1.2.1 import harpoon.ClassFile.HField; 10 duncan 1.1.2.1 import harpoon.IR.Tree.NAME; 11 duncan 1.1.2.1 import harpoon.Util.HClassUtil; 12 duncan 1.1.2.1 import harpoon.Util.Util; 13 duncan 1.1.2.1 14 duncan 1.1.2.1 /** 15 duncan 1.1.2.1 * <code>ArrayRef</code> is a representation of an array reference for use 16 duncan 1.1.2.1 * by the interpreter. 17 duncan 1.1.2.1 * 18 duncan 1.1.2.1 * @author C. Scott Ananian <cananian@alumni.princeton.edu> 19 cananian 1.4 * @version $Id: ArrayRef.java,v 1.4 2002/04/10 03:05:55 cananian Exp $ 20 duncan 1.1.2.1 */ 21 duncan 1.1.2.1 final class ArrayRef extends Ref { 22 duncan 1.1.2.1 /** Elements of the array (primitives or Refs) */ 23 cananian 1.3.2.2 final Object[] elements; 24 duncan 1.1.2.1 private Integer hashCode = null; 25 duncan 1.1.2.1 private Integer length = null; 26 duncan 1.1.2.1 private ClazPointer classPtr = null; 27 duncan 1.1.2.1 28 duncan 1.1.2.1 /** Class constructor. */ 29 duncan 1.1.2.1 ArrayRef(StaticState ss, HClass type, int[] dims) 30 duncan 1.1.2.1 throws InterpretedThrowable { 31 duncan 1.1.2.1 this(ss, type, dims, null, null, null); 32 duncan 1.1.2.1 } 33 duncan 1.1.2.1 34 duncan 1.1.2.1 /** Class constructor. */ 35 duncan 1.1.2.1 ArrayRef(StaticState ss, HClass type, int[] dims, 36 duncan 1.1.2.1 Integer length, Integer hashCode, ClazPointer classPtr) 37 duncan 1.1.2.1 throws InterpretedThrowable { 38 duncan 1.1.2.1 super(ss, type); 39 duncan 1.1.2.1 40 cananian 1.3.2.1 assert dims.length >= 1 && dims[0]>=0; 41 duncan 1.1.2.1 this.elements = new Object[dims[0]]; 42 duncan 1.1.2.1 this.length = length==null?new Integer(dims[0]):length; 43 duncan 1.1.2.1 this.hashCode = hashCode==null?new Integer(this.hashCode()):hashCode; 44 duncan 1.1.2.1 this.classPtr = classPtr==null? 45 duncan 1.1.2.1 new ClazPointer(ss.map.label(type), ss, 0):classPtr; 46 duncan 1.1.2.1 47 duncan 1.1.2.1 if (dims.length==1) 48 duncan 1.1.2.1 for (int i=0; i<this.elements.length; i++) 49 duncan 1.1.2.1 this.elements[i] = defaultValue(type.getComponentType()); 50 duncan 1.1.2.1 else { 51 duncan 1.1.2.1 int ndims[] = new int[dims.length-1]; 52 duncan 1.1.2.1 System.arraycopy(dims, 1, ndims, 0, ndims.length); 53 duncan 1.1.2.1 for (int i=0; i<this.elements.length; i++) { 54 duncan 1.1.2.1 System.err.println("*** Warning, unexpected # of dims!"); 55 duncan 1.1.2.1 this.elements[i] = 56 duncan 1.1.2.1 new ArrayRef(ss, type.getComponentType(), ndims); 57 duncan 1.1.2.1 } 58 duncan 1.1.2.1 } 59 duncan 1.1.2.1 } 60 duncan 1.1.2.1 61 duncan 1.1.2.1 // private constructor for use by clone() method 62 pnkfelix 1.1.2.2 private ArrayRef(StaticState ss, HClass type, final Object[] elements) { 63 duncan 1.1.2.1 super(ss, type); 64 duncan 1.1.2.1 this.elements = elements; 65 cananian 1.3.2.1 assert elements!=null; 66 duncan 1.1.2.1 } 67 duncan 1.1.2.1 68 duncan 1.1.2.1 public Object clone() { // arrays can always be cloned. 69 duncan 1.1.2.1 return new ArrayRef(ss, type, (Object[]) elements.clone()); 70 duncan 1.1.2.1 } 71 duncan 1.1.2.1 72 duncan 1.1.2.1 73 duncan 1.1.2.1 /** Returns the length of this array. The length field can also be 74 duncan 1.1.2.1 * accesses with an <code>ArrayPointer</code> which has a base of this 75 duncan 1.1.2.1 * <code>ArrayRef</code>, and an offset equal to the lengthOffset 76 duncan 1.1.2.1 * of the interpreter's offset map. */ 77 duncan 1.1.2.1 int length() { return length.intValue(); } 78 duncan 1.1.2.1 79 duncan 1.1.2.1 /** Returns the i'th element of the array represented by this 80 duncan 1.1.2.1 * <code>ArrayRef</code> 81 duncan 1.1.2.1 */ 82 duncan 1.1.2.1 Object get(int i){ 83 duncan 1.1.2.1 if (this.elements.length <= i) 84 duncan 1.1.2.1 throw new Error 85 duncan 1.1.2.1 ("ArrayOutOfBounds exception should have been thrown"); 86 duncan 1.1.2.1 else 87 duncan 1.1.2.1 return this.elements[i]; 88 duncan 1.1.2.1 } 89 duncan 1.1.2.1 90 duncan 1.1.2.1 /** Sets the i'th element of the array represented by this 91 duncan 1.1.2.1 * <code>ArrayRef<code> to be <code>value</code>. 92 duncan 1.1.2.1 */ 93 duncan 1.1.2.1 void update(int i, Object value) { 94 duncan 1.1.2.1 if (this.elements.length <= i) { 95 duncan 1.1.2.1 throw new Error("Should've thrown ArrayOutOfBoundsException"); 96 duncan 1.1.2.1 } 97 duncan 1.1.2.1 else { 98 duncan 1.1.2.1 this.elements[i] = value; 99 duncan 1.1.2.1 } 100 duncan 1.1.2.1 } 101 duncan 1.1.2.1 102 duncan 1.1.2.1 /** Provides yet another method to access the length field of this 103 duncan 1.1.2.1 * <code>ArrayRef</code>. 104 duncan 1.1.2.1 */ 105 duncan 1.1.2.1 Object get(HField field) { 106 duncan 1.1.2.1 if (field.getName().equals("length")) return length; 107 duncan 1.1.2.1 else throw new Error("Field not found: "+ field.getName()); 108 duncan 1.1.2.1 } 109 duncan 1.1.2.1 110 duncan 1.1.2.1 111 duncan 1.1.2.1 /** Returns a human-readable representation of this <code>ArrayRef</code> 112 duncan 1.1.2.1 */ 113 duncan 1.1.2.3 /* public String toString() { 114 duncan 1.1.2.1 StringBuffer sb = new StringBuffer(); 115 duncan 1.1.2.1 sb.append("ArrayRef: <"); 116 duncan 1.1.2.1 sb.append(HClassUtil.baseClass(type)); 117 duncan 1.1.2.1 sb.append('['); sb.append(elements.length); sb.append(']'); 118 duncan 1.1.2.1 for (int i=1; i<HClassUtil.dims(type); i++) 119 duncan 1.1.2.1 sb.append("[]"); 120 duncan 1.1.2.1 sb.append('>'); 121 duncan 1.1.2.1 return sb.toString(); 122 duncan 1.1.2.3 } */ 123 duncan 1.1.2.1 124 duncan 1.1.2.1 125 duncan 1.1.2.1 /** Returns the value obtained by dereferencing the specified 126 duncan 1.1.2.1 * <code>ArrayPointer</code>. The value returned will be 127 duncan 1.1.2.1 * in native format. 128 duncan 1.1.2.1 */ 129 duncan 1.1.2.1 static Object get(ArrayPointer ptr) { 130 duncan 1.1.2.1 ArrayRef ref = (ArrayRef)ptr.getBase(); 131 duncan 1.1.2.1 long offset = ptr.getOffset(); 132 duncan 1.1.2.1 133 duncan 1.1.2.1 if (ref.ss.map.lengthOffset(ref.type)==offset) { 134 cananian 1.3.2.1 assert ref.length!=null; 135 duncan 1.1.2.1 return ref.length; 136 duncan 1.1.2.1 } 137 duncan 1.1.2.1 else if (ref.ss.map.hashCodeOffset(ref.type)==offset) { 138 cananian 1.3.2.1 assert ref.hashCode!=null; 139 duncan 1.1.2.1 return ref.hashCode; 140 duncan 1.1.2.1 } 141 duncan 1.1.2.6 else if (ref.ss.map.clazzPtrOffset(ref.type)==offset) { 142 cananian 1.3.2.1 assert ref.classPtr!=null; 143 duncan 1.1.2.1 return ref.classPtr; 144 duncan 1.1.2.1 } 145 duncan 1.1.2.1 else return ref.get((int)offset); 146 duncan 1.1.2.1 } 147 duncan 1.1.2.1 148 duncan 1.1.2.1 /** Updates the value pointed to by <code>ptr</code>. The 149 duncan 1.1.2.1 * <code>value</code> parameter must be in native format. 150 duncan 1.1.2.1 */ 151 duncan 1.1.2.1 static void update(ArrayPointer ptr, Object value) { 152 duncan 1.1.2.1 ArrayRef ref = (ArrayRef)ptr.getBase(); 153 duncan 1.1.2.1 long offset = ptr.getOffset(); 154 duncan 1.1.2.1 155 duncan 1.1.2.1 if (ref.ss.map.lengthOffset(ref.type)==offset) { 156 duncan 1.1.2.1 throw new Error("The length field of an array is final"); 157 duncan 1.1.2.1 } 158 duncan 1.1.2.1 else if (ref.ss.map.hashCodeOffset(ref.type)==offset) { 159 duncan 1.1.2.1 throw new Error("The hashcode field of an array is final"); 160 duncan 1.1.2.1 } 161 duncan 1.1.2.6 else if (ref.ss.map.clazzPtrOffset(ref.type)==offset) { 162 duncan 1.1.2.1 throw new Error("The clazpointer of an array is final"); 163 duncan 1.1.2.1 } 164 duncan 1.1.2.1 else { 165 duncan 1.1.2.1 ref.update((int)offset, value); 166 duncan 1.1.2.1 } 167 duncan 1.1.2.1 } 168 duncan 1.1.2.1 } 169 cananian 1.2