/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.opensource.org/licenses/eclipse-1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.jikesrvm.classloader; import java.util.WeakHashMap; /** * Lightweight implementation of a vector of Fields. This class is intended * to be used by a single thread and is therefore not thread-safe. */ final class MethodVector { //-----------// // interface // //-----------// MethodVector() { array = new RVMMethod[10]; } void addElement(RVMMethod item) { if (cnt == array.length) { adjustLength(cnt << 1); // double size of array } array[cnt++] = item; } /** * Adds an item if it is not already in the vector. The test * for the item uses the method descriptor and the method * name. * * @param item method to be added */ public void addUniqueElement(RVMMethod item) { for (int i = 0; i < cnt; i++) { RVMMethod currentMethod = array[i]; if (item.getDescriptor() == currentMethod.getDescriptor() && item.getName() == currentMethod.getName()) { return; } } addElement(item); } RVMMethod elementAt(int index) { return array[index]; } void setElementAt(RVMMethod item, int index) { array[index] = item; } public int size() { return cnt; } /** * * @return an array of methods, trimmed to size. The returned array * is canonical: Adding the same set of methods in the same order * to different newly-created vectors {@code v1} and {@code v2} * will lead to the same array being returned for both {@code v1} * and {@code v2} when this method is called. */ public RVMMethod[] finish() { synchronized (MethodVector.class) { RVMMethod[] result = popularMVs.get(this); if (result != null) { array = result; return result; } else { adjustLength(cnt); popularMVs.put(this, array); return array; } } } @Override public int hashCode() { int val = 0; for (int i = cnt - 1; i >= 0; i--) { val ^= array[i].hashCode(); } return val; } @Override public boolean equals(Object obj) { if (obj instanceof MethodVector) { MethodVector that = (MethodVector)obj; if (cnt != that.cnt) return false; for (int i = cnt - 1; i >= 0; i--) { if (array[i] != that.array[i]) return false; } return true; } else { return false; } } //----------------// // implementation // //----------------// private RVMMethod[] array; private int cnt; private static final RVMMethod[] empty = new RVMMethod[0]; private static final WeakHashMap<MethodVector, RVMMethod[]> popularMVs = new WeakHashMap<MethodVector, RVMMethod[]>(); private void adjustLength(int newLength) { if (newLength == 0) { array = empty; } else { RVMMethod[] newElements = new RVMMethod[newLength]; int n = array.length; if (n > newLength) { n = newLength; } for (int i = 0; i < n; ++i) { newElements[i] = array[i]; } array = newElements; } } }