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 FieldVector {
021      //-----------//
022      // interface //
023      //-----------//
024    
025      public FieldVector() {
026        array = new RVMField[10];
027      }
028    
029      // Add item.
030      //
031      void addElement(RVMField 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(RVMField 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      RVMField elementAt(int index) {
050        return array[index];
051      }
052    
053      // Set item.
054      //
055      void setElementAt(RVMField 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 RVMField[] finish() {
068        RVMField[] result = popularFVs.get(this);
069        if (result != null) {
070          array = result;
071          return result;
072        } else {
073          adjustLength(cnt);
074          popularFVs.put(this, array);
075          return array;
076        }
077      }
078    
079      @Override
080      public int hashCode() {
081        int val = 0;
082        for (int i=cnt-1; i >= 0; i--) {
083          val ^= array[i].hashCode();
084        }
085        return val;
086      }
087    
088      @Override
089      public boolean equals(Object obj) {
090        if (obj instanceof FieldVector) {
091          FieldVector that = (FieldVector)obj;
092          if (cnt != that.cnt) return false;
093          for(int i=cnt-1; i>=0; i--) {
094            if (array[i] != that.array[i]) return false;
095          }
096          return true;
097        } else {
098          return false;
099        }
100      }
101    
102      //----------------//
103      // implementation //
104      //----------------//
105    
106      private RVMField[] array;
107      private int cnt;
108    
109      private static final RVMField[] empty = new RVMField[0];
110      private static final WeakHashMap<FieldVector, RVMField[]>
111        popularFVs = new WeakHashMap<FieldVector, RVMField[]>();
112    
113      private void adjustLength(int newLength) {
114        if (newLength == 0) {
115          array = empty;
116        } else {
117          RVMField[] newElements = new RVMField[newLength];
118          int n = array.length;
119          if (n > newLength) {
120            n = newLength;
121          }
122    
123          for (int i = 0; i < n; ++i) {
124            newElements[i] = array[i];
125          }
126    
127          array = newElements;
128        }
129      }
130    }