1.1 --- a/src/share/classes/com/sun/tools/javac/code/Scope.java Fri Oct 29 13:12:38 2010 -0700 1.2 +++ b/src/share/classes/com/sun/tools/javac/code/Scope.java Mon Nov 01 19:28:40 2010 -0700 1.3 @@ -1,5 +1,5 @@ 1.4 /* 1.5 - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 1.6 + * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved. 1.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.8 * 1.9 * This code is free software; you can redistribute it and/or modify it 1.10 @@ -31,8 +31,7 @@ 1.11 /** A scope represents an area of visibility in a Java program. The 1.12 * Scope class is a container for symbols which provides 1.13 * efficient access to symbols given their names. Scopes are implemented 1.14 - * as hash tables with "open addressing" and "double hashing". 1.15 - * Scopes can be nested; the next field of a scope points 1.16 + * as hash tables. Scopes can be nested; the next field of a scope points 1.17 * to its next outer scope. Nested scopes can share their hash tables. 1.18 * 1.19 * <p><b>This is NOT part of any supported API. 1.20 @@ -68,7 +67,6 @@ 1.21 public Entry elems; 1.22 1.23 /** The number of elements in this scope. 1.24 - * This includes deleted elements, whose value is the sentinel. 1.25 */ 1.26 public int nelems = 0; 1.27 1.28 @@ -111,8 +109,7 @@ 1.29 } 1.30 } 1.31 1.32 - /** Use as a "not-found" result for lookup. 1.33 - * Also used to mark deleted entries in the table. 1.34 + /** Every hash bucket is a list of Entry's which ends in sentinel. 1.35 */ 1.36 private static final Entry sentinel = new Entry(null, null, null, null); 1.37 1.38 @@ -133,15 +130,12 @@ 1.39 this.owner = owner; 1.40 this.table = table; 1.41 this.hashMask = table.length - 1; 1.42 + this.elems = null; 1.43 + this.nelems = 0; 1.44 + this.shared = 0; 1.45 this.scopeCounter = scopeCounter; 1.46 } 1.47 1.48 - /** Convenience constructor used for dup and dupUnshared. */ 1.49 - private Scope(Scope next, Symbol owner, Entry[] table) { 1.50 - this(next, owner, table, next.scopeCounter); 1.51 - this.nelems = next.nelems; 1.52 - } 1.53 - 1.54 /** Construct a new scope, within scope next, with given owner, 1.55 * using a fresh table of length INITIAL_SIZE. 1.56 */ 1.57 @@ -151,6 +145,7 @@ 1.58 1.59 protected Scope(Symbol owner, ScopeCounter scopeCounter) { 1.60 this(null, owner, new Entry[INITIAL_SIZE], scopeCounter); 1.61 + for (int i = 0; i < INITIAL_SIZE; i++) table[i] = sentinel; 1.62 } 1.63 1.64 /** Construct a fresh scope within this scope, with same owner, 1.65 @@ -159,7 +154,11 @@ 1.66 * of fresh tables. 1.67 */ 1.68 public Scope dup() { 1.69 - return dup(this.owner); 1.70 + Scope result = new Scope(this, this.owner, this.table, scopeCounter); 1.71 + shared++; 1.72 + // System.out.println("====> duping scope " + this.hashCode() + " owned by " + this.owner + " to " + result.hashCode()); 1.73 + // new Error().printStackTrace(System.out); 1.74 + return result; 1.75 } 1.76 1.77 /** Construct a fresh scope within this scope, with new owner, 1.78 @@ -168,7 +167,7 @@ 1.79 * of fresh tables. 1.80 */ 1.81 public Scope dup(Symbol newOwner) { 1.82 - Scope result = new Scope(this, newOwner, this.table); 1.83 + Scope result = new Scope(this, newOwner, this.table, scopeCounter); 1.84 shared++; 1.85 // System.out.println("====> duping scope " + this.hashCode() + " owned by " + newOwner + " to " + result.hashCode()); 1.86 // new Error().printStackTrace(System.out); 1.87 @@ -180,7 +179,7 @@ 1.88 * the table of its outer scope. 1.89 */ 1.90 public Scope dupUnshared() { 1.91 - return new Scope(this, this.owner, this.table.clone()); 1.92 + return new Scope(this, this.owner, this.table.clone(), scopeCounter); 1.93 } 1.94 1.95 /** Remove all entries of this scope from its table, if shared 1.96 @@ -190,7 +189,7 @@ 1.97 assert shared == 0; 1.98 if (table != next.table) return next; 1.99 while (elems != null) { 1.100 - int hash = getIndex(elems.sym.name); 1.101 + int hash = elems.sym.name.hashCode() & hashMask; 1.102 Entry e = table[hash]; 1.103 assert e == elems : elems.sym; 1.104 table[hash] = elems.shadowed; 1.105 @@ -198,7 +197,6 @@ 1.106 } 1.107 assert next.shared > 0; 1.108 next.shared--; 1.109 - next.nelems = nelems; 1.110 // System.out.println("====> leaving scope " + this.hashCode() + " owned by " + this.owner + " to " + next.hashCode()); 1.111 // new Error().printStackTrace(System.out); 1.112 return next; 1.113 @@ -217,17 +215,19 @@ 1.114 s.hashMask = newtable.length - 1; 1.115 } 1.116 } 1.117 - int n = 0; 1.118 - for (int i = oldtable.length; --i >= 0; ) { 1.119 - Entry e = oldtable[i]; 1.120 - if (e != null && e != sentinel) { 1.121 - table[getIndex(e.sym.name)] = e; 1.122 - n++; 1.123 - } 1.124 + for (int i = 0; i < newtable.length; i++) newtable[i] = sentinel; 1.125 + for (int i = 0; i < oldtable.length; i++) copy(oldtable[i]); 1.126 + } 1.127 + 1.128 + /** Copy the given entry and all entries shadowed by it to table 1.129 + */ 1.130 + private void copy(Entry e) { 1.131 + if (e.sym != null) { 1.132 + copy(e.shadowed); 1.133 + int hash = e.sym.name.hashCode() & hashMask; 1.134 + e.shadowed = table[hash]; 1.135 + table[hash] = e; 1.136 } 1.137 - // We don't need to update nelems for shared inherited scopes, 1.138 - // since that gets handled by leave(). 1.139 - nelems = n; 1.140 } 1.141 1.142 /** Enter symbol sym in this scope. 1.143 @@ -248,17 +248,13 @@ 1.144 */ 1.145 public void enter(Symbol sym, Scope s, Scope origin) { 1.146 assert shared == 0; 1.147 - if (nelems * 3 >= hashMask * 2) 1.148 - dble(); 1.149 - int hash = getIndex(sym.name); 1.150 - Entry old = table[hash]; 1.151 - if (old == null) { 1.152 - old = sentinel; 1.153 - nelems++; 1.154 - } 1.155 - Entry e = makeEntry(sym, old, elems, s, origin); 1.156 + // Temporarily disabled (bug 6460352): 1.157 + // if (nelems * 3 >= hashMask * 2) dble(); 1.158 + int hash = sym.name.hashCode() & hashMask; 1.159 + Entry e = makeEntry(sym, table[hash], elems, s, origin); 1.160 table[hash] = e; 1.161 elems = e; 1.162 + nelems++; 1.163 scopeCounter.inc(); 1.164 } 1.165 1.166 @@ -272,15 +268,15 @@ 1.167 public void remove(Symbol sym) { 1.168 assert shared == 0; 1.169 Entry e = lookup(sym.name); 1.170 + while (e.scope == this && e.sym != sym) e = e.next(); 1.171 if (e.scope == null) return; 1.172 1.173 scopeCounter.inc(); 1.174 1.175 // remove e from table and shadowed list; 1.176 - int i = getIndex(sym.name); 1.177 - Entry te = table[i]; 1.178 + Entry te = table[sym.name.hashCode() & hashMask]; 1.179 if (te == e) 1.180 - table[i] = e.shadowed; 1.181 + table[sym.name.hashCode() & hashMask] = e.shadowed; 1.182 else while (true) { 1.183 if (te.shadowed == e) { 1.184 te.shadowed = e.shadowed; 1.185 @@ -339,50 +335,12 @@ 1.186 return lookup(name, noFilter); 1.187 } 1.188 public Entry lookup(Name name, Filter<Symbol> sf) { 1.189 - Entry e = table[getIndex(name)]; 1.190 - if (e == null || e == sentinel) 1.191 - return sentinel; 1.192 + Entry e = table[name.hashCode() & hashMask]; 1.193 while (e.scope != null && (e.sym.name != name || !sf.accepts(e.sym))) 1.194 e = e.shadowed; 1.195 return e; 1.196 } 1.197 1.198 - /*void dump (java.io.PrintStream out) { 1.199 - out.println(this); 1.200 - for (int l=0; l < table.length; l++) { 1.201 - Entry le = table[l]; 1.202 - out.print("#"+l+": "); 1.203 - if (le==sentinel) out.println("sentinel"); 1.204 - else if(le == null) out.println("null"); 1.205 - else out.println(""+le+" s:"+le.sym); 1.206 - } 1.207 - }*/ 1.208 - 1.209 - /** Look for slot in the table. 1.210 - * We use open addressing with double hashing. 1.211 - */ 1.212 - int getIndex (Name name) { 1.213 - int h = name.hashCode(); 1.214 - int i = h & hashMask; 1.215 - // The expression below is always odd, so it is guaranteed 1.216 - // be be mutually prime with table.length, a power of 2. 1.217 - int x = hashMask - ((h + (h >> 16)) << 1); 1.218 - int d = -1; // Index of a deleted item. 1.219 - for (;;) { 1.220 - Entry e = table[i]; 1.221 - if (e == null) 1.222 - return d >= 0 ? d : i; 1.223 - if (e == sentinel) { 1.224 - // We have to keep searching even if we see a deleted item. 1.225 - // However, remember the index in case we fail to find the name. 1.226 - if (d < 0) 1.227 - d = i; 1.228 - } else if (e.sym.name == name) 1.229 - return i; 1.230 - i = (i + x) & hashMask; 1.231 - } 1.232 - } 1.233 - 1.234 public Iterable<Symbol> getElements() { 1.235 return getElements(noFilter); 1.236 } 1.237 @@ -512,11 +470,10 @@ 1.238 } 1.239 1.240 public Entry lookup(Name name) { 1.241 - Entry e = table[getIndex(name)]; 1.242 - if (e == null) 1.243 - return sentinel; 1.244 + Entry e = table[name.hashCode() & hashMask]; 1.245 while (e.scope != null && 1.246 - (/* Since an inner class will show up in package and 1.247 + (e.sym.name != name || 1.248 + /* Since an inner class will show up in package and 1.249 * import scopes until its inner class attribute has 1.250 * been processed, we have to weed it out here. This 1.251 * is done by comparing the owners of the entry's