UnsharedNameTable.java revision 2571:10fc81ac75b4
1/* 2 * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package com.sun.tools.javac.util; 27 28import java.lang.ref.WeakReference; 29 30/** 31 * Implementation of Name.Table that stores names in individual arrays 32 * using weak references. It is recommended for use when a single shared 33 * byte array is unsuitable. 34 * 35 * <p><b>This is NOT part of any supported API. 36 * If you write code that depends on this, you do so at your own risk. 37 * This code and its internal interfaces are subject to change or 38 * deletion without notice.</b> 39 */ 40public class UnsharedNameTable extends Name.Table { 41 static public Name.Table create(Names names) { 42 return new UnsharedNameTable(names); 43 } 44 45 static class HashEntry extends WeakReference<NameImpl> { 46 HashEntry next; 47 HashEntry(NameImpl referent) { 48 super(referent); 49 } 50 } 51 52 /** The hash table for names. 53 */ 54 private HashEntry[] hashes = null; 55 56 /** The mask to be used for hashing 57 */ 58 private int hashMask; 59 60 /** Index counter for names in this table. 61 */ 62 public int index; 63 64 /** Allocator 65 * @param names The main name table 66 * @param hashSize the (constant) size to be used for the hash table 67 * needs to be a power of two. 68 */ 69 public UnsharedNameTable(Names names, int hashSize) { 70 super(names); 71 hashMask = hashSize - 1; 72 hashes = new HashEntry[hashSize]; 73 } 74 75 public UnsharedNameTable(Names names) { 76 this(names, 0x8000); 77 } 78 79 80 @Override 81 public Name fromChars(char[] cs, int start, int len) { 82 byte[] name = new byte[len * 3]; 83 int nbytes = Convert.chars2utf(cs, start, name, 0, len); 84 return fromUtf(name, 0, nbytes); 85 } 86 87 @Override 88 public Name fromUtf(byte[] cs, int start, int len) { 89 int h = hashValue(cs, start, len) & hashMask; 90 91 HashEntry element = hashes[h]; 92 93 NameImpl n = null; 94 95 HashEntry previousNonNullTableEntry = null; 96 HashEntry firstTableEntry = element; 97 98 while (element != null) { 99 if (element == null) { 100 break; 101 } 102 103 n = element.get(); 104 105 if (n == null) { 106 if (firstTableEntry == element) { 107 hashes[h] = firstTableEntry = element.next; 108 } 109 else { 110 Assert.checkNonNull(previousNonNullTableEntry, "previousNonNullTableEntry cannot be null here."); 111 previousNonNullTableEntry.next = element.next; 112 } 113 } 114 else { 115 if (n.getByteLength() == len && equals(n.bytes, 0, cs, start, len)) { 116 return n; 117 } 118 previousNonNullTableEntry = element; 119 } 120 121 element = element.next; 122 } 123 124 byte[] bytes = new byte[len]; 125 System.arraycopy(cs, start, bytes, 0, len); 126 n = new NameImpl(this, bytes, index++); 127 128 HashEntry newEntry = new HashEntry(n); 129 130 if (previousNonNullTableEntry == null) { // We are not the first name with that hashCode. 131 hashes[h] = newEntry; 132 } 133 else { 134 Assert.checkNull(previousNonNullTableEntry.next, "previousNonNullTableEntry.next must be null."); 135 previousNonNullTableEntry.next = newEntry; 136 } 137 138 return n; 139 } 140 141 @Override 142 public void dispose() { 143 hashes = null; 144 } 145 146 static class NameImpl extends Name { 147 NameImpl(UnsharedNameTable table, byte[] bytes, int index) { 148 super(table); 149 this.bytes = bytes; 150 this.index = index; 151 } 152 153 final byte[] bytes; 154 final int index; 155 156 @Override 157 public int getIndex() { 158 return index; 159 } 160 161 @Override 162 public int getByteLength() { 163 return bytes.length; 164 } 165 166 @Override 167 public byte getByteAt(int i) { 168 return bytes[i]; 169 } 170 171 @Override 172 public byte[] getByteArray() { 173 return bytes; 174 } 175 176 @Override 177 public int getByteOffset() { 178 return 0; 179 } 180 181 } 182 183} 184