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 FieldVector { 022 //-----------// 023 // interface // 024 //-----------// 025 026 FieldVector() { 027 array = new RVMField[10]; 028 } 029 030 void addElement(RVMField item) { 031 if (cnt == array.length) { 032 adjustLength(cnt << 1); // double size of array 033 } 034 array[cnt++] = item; 035 } 036 037 /** 038 * @return an array of fields, trimmed to size. The returned array 039 * is canonical: Adding the same set of fields in the same order 040 * to different newly-created vectors {@code v1} and {@code v2} 041 * will lead to the same array being returned for both {@code v1} 042 * and {@code v2} when this method is called. 043 */ 044 public RVMField[] finish() { 045 synchronized (RVMField.class) { 046 RVMField[] result = popularFVs.get(this); 047 if (result != null) { 048 array = result; 049 return result; 050 } else { 051 adjustLength(cnt); 052 popularFVs.put(this, array); 053 return array; 054 } 055 } 056 } 057 058 @Override 059 public int hashCode() { 060 int val = 0; 061 for (int i = cnt - 1; i >= 0; i--) { 062 val ^= array[i].hashCode(); 063 } 064 return val; 065 } 066 067 @Override 068 public boolean equals(Object obj) { 069 if (obj instanceof FieldVector) { 070 FieldVector that = (FieldVector)obj; 071 if (cnt != that.cnt) return false; 072 for (int i = cnt - 1; i >= 0; i--) { 073 if (array[i] != that.array[i]) return false; 074 } 075 return true; 076 } else { 077 return false; 078 } 079 } 080 081 //----------------// 082 // implementation // 083 //----------------// 084 085 private RVMField[] array; 086 private int cnt; 087 088 private static final RVMField[] empty = new RVMField[0]; 089 private static final WeakHashMap<FieldVector, RVMField[]> 090 popularFVs = new WeakHashMap<FieldVector, RVMField[]>(); 091 092 private void adjustLength(int newLength) { 093 if (newLength == 0) { 094 array = empty; 095 } else { 096 RVMField[] newElements = new RVMField[newLength]; 097 int n = array.length; 098 if (n > newLength) { 099 n = newLength; 100 } 101 102 for (int i = 0; i < n; ++i) { 103 newElements[i] = array[i]; 104 } 105 106 array = newElements; 107 } 108 } 109}