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