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 */
013package org.jikesrvm.classloader;
014
015import java.util.WeakHashMap;
016
017/**
018 *  Lightweight implementation of a vector of Fields.
019 */
020final class TypeReferenceVector {
021  //-----------//
022  // interface //
023  //-----------//
024
025  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  @Override
080  public int hashCode() {
081    int val = 0;
082    for (int i = 0; i < cnt; i++) {
083      val ^= array[i].hashCode();
084    }
085    return val;
086  }
087
088  @Override
089  public boolean equals(Object obj) {
090    if (obj instanceof TypeReferenceVector) {
091      TypeReferenceVector that = (TypeReferenceVector)obj;
092      if (cnt != that.cnt) return false;
093      for (int i = 0; i < cnt; 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 TypeReference[] array;
107  private int cnt;
108
109  private static final TypeReference[] empty = new TypeReference[0];
110  private static final WeakHashMap<TypeReferenceVector,TypeReference[]>
111    popularTRVs = new WeakHashMap<TypeReferenceVector,TypeReference[]>();
112
113  private void adjustLength(int newLength) {
114    if (newLength == 0) {
115      array = empty;
116    } else {
117      TypeReference[] newElements = new TypeReference[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}