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. This class is intended 019 * to be used by a single thread and is therefore not thread-safe. 020 */ 021final class MethodVector { 022 //-----------// 023 // interface // 024 //-----------// 025 026 MethodVector() { 027 array = new RVMMethod[10]; 028 } 029 030 void addElement(RVMMethod item) { 031 if (cnt == array.length) { 032 adjustLength(cnt << 1); // double size of array 033 } 034 array[cnt++] = item; 035 } 036 037 /** 038 * Adds an item if it is not already in the vector. The test 039 * for the item uses object identity. 040 * 041 * @param item method to be added 042 */ 043 public void addUniqueElement(RVMMethod item) { 044 for (int i = 0; i < cnt; i++) { 045 if (array[i] == item) return; 046 } 047 addElement(item); 048 } 049 050 RVMMethod elementAt(int index) { 051 return array[index]; 052 } 053 054 void setElementAt(RVMMethod item, int index) { 055 array[index] = item; 056 } 057 058 public int size() { 059 return cnt; 060 } 061 062 /** 063 * 064 * @return an array of methods, trimmed to size. The returned array 065 * is canonical: Adding the same set of methods in the same order 066 * to different newly-created vectors {@code v1} and {@code v2} 067 * will lead to the same array being returned for both {@code v1} 068 * and {@code v2} when this method is called. 069 */ 070 public RVMMethod[] finish() { 071 synchronized (MethodVector.class) { 072 RVMMethod[] result = popularMVs.get(this); 073 if (result != null) { 074 array = result; 075 return result; 076 } else { 077 adjustLength(cnt); 078 popularMVs.put(this, array); 079 return array; 080 } 081 } 082 } 083 084 @Override 085 public int hashCode() { 086 int val = 0; 087 for (int i = cnt - 1; i >= 0; i--) { 088 val ^= array[i].hashCode(); 089 } 090 return val; 091 } 092 093 @Override 094 public boolean equals(Object obj) { 095 if (obj instanceof MethodVector) { 096 MethodVector that = (MethodVector)obj; 097 if (cnt != that.cnt) return false; 098 for (int i = cnt - 1; i >= 0; i--) { 099 if (array[i] != that.array[i]) return false; 100 } 101 return true; 102 } else { 103 return false; 104 } 105 } 106 107 //----------------// 108 // implementation // 109 //----------------// 110 111 private RVMMethod[] array; 112 private int cnt; 113 114 private static final RVMMethod[] empty = new RVMMethod[0]; 115 private static final WeakHashMap<MethodVector, RVMMethod[]> 116 popularMVs = new WeakHashMap<MethodVector, RVMMethod[]>(); 117 118 private void adjustLength(int newLength) { 119 if (newLength == 0) { 120 array = empty; 121 } else { 122 RVMMethod[] newElements = new RVMMethod[newLength]; 123 int n = array.length; 124 if (n > newLength) { 125 n = newLength; 126 } 127 128 for (int i = 0; i < n; ++i) { 129 newElements[i] = array[i]; 130 } 131 132 array = newElements; 133 } 134 } 135}