001    /*
002     *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003     *
004     *  This file is licensed to You under the Eclipse Public License (EPL);
005     *  You may not use this file except in compliance with the License. You
006     *  may obtain a copy of the License at
007     *
008     *      http://www.opensource.org/licenses/eclipse-1.0.php
009     *
010     *  See the COPYRIGHT.txt file distributed with this work for information
011     *  regarding copyright ownership.
012     */
013    package org.jikesrvm.classloader;
014    
015    import java.util.WeakHashMap;
016    
017    /**
018     *  Lightweight implementation of a vector of Fields.
019     */
020    final class TypeReferenceVector {
021      //-----------//
022      // interface //
023      //-----------//
024    
025      public TypeReferenceVector() {
026        array = new TypeReference[10];
027      }
028    
029      // Add item.
030      //
031      void addElement(TypeReference item) {
032        if (cnt == array.length) {
033          adjustLength(cnt << 1); // double size of array
034        }
035        array[cnt++] = item;
036      }
037    
038      // Add item if it is not already in the Vector.
039      //
040      public void addUniqueElement(TypeReference item) {
041        for (int i = 0; i < cnt; i++) {
042          if (array[i] == item) return;
043        }
044        addElement(item);
045      }
046    
047      // Get item.
048      //
049      TypeReference elementAt(int index) {
050        return array[index];
051      }
052    
053      // Set item.
054      //
055      void setElementAt(TypeReference item, int index) {
056        array[index] = item;
057      }
058    
059      // Get number of items added so far.
060      //
061      public int size() {
062        return cnt;
063      }
064    
065      // Get array, trimmed to size.
066      //
067      public TypeReference[] finish() {
068        TypeReference[] result = popularTRVs.get(this);
069        if (result != null) {
070          array = result;
071          return result;
072        } else {
073          adjustLength(cnt);
074          popularTRVs.put(this, array);
075          return array;
076        }
077      }
078    
079      public int hashCode() {
080        int val=0;
081        for(int i=0; i<cnt; i++) {
082          val ^= array[i].hashCode();
083        }
084        return val;
085      }
086    
087      public boolean equals(Object obj) {
088        if (obj instanceof TypeReferenceVector) {
089          TypeReferenceVector that = (TypeReferenceVector)obj;
090          if (cnt != that.cnt) return false;
091          for(int i=0; i<cnt; i++) {
092            if (array[i] != that.array[i]) return false;
093          }
094          return true;
095        } else {
096          return false;
097        }
098      }
099    
100      //----------------//
101      // implementation //
102      //----------------//
103    
104      private TypeReference[] array;
105      private int cnt;
106    
107      private static final TypeReference[] empty = new TypeReference[0];
108      private static final WeakHashMap<TypeReferenceVector,TypeReference[]>
109        popularTRVs = new WeakHashMap<TypeReferenceVector,TypeReference[]>();
110    
111      private void adjustLength(int newLength) {
112        if (newLength == 0) {
113          array = empty;
114        } else {
115          TypeReference[] newElements = new TypeReference[newLength];
116          int n = array.length;
117          if (n > newLength) {
118            n = newLength;
119          }
120    
121          for (int i = 0; i < n; ++i) {
122            newElements[i] = array[i];
123          }
124    
125          array = newElements;
126        }
127      }
128    }