# HG changeset patch # User jjg # Date 1288664920 25200 # Node ID 8666b4fbb99bb2c81e2f58f50abd0093475500e4 # Parent 17f1f2bdcb4636718d06a07af982bb2983e8c28c 6996626: Scope fix issues for ImportScope Reviewed-by: darcy diff -r 17f1f2bdcb46 -r 8666b4fbb99b langtools/src/share/classes/com/sun/tools/javac/code/Scope.java --- a/langtools/src/share/classes/com/sun/tools/javac/code/Scope.java Fri Oct 29 13:12:38 2010 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Scope.java Mon Nov 01 19:28:40 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,8 +31,7 @@ /** A scope represents an area of visibility in a Java program. The * Scope class is a container for symbols which provides * efficient access to symbols given their names. Scopes are implemented - * as hash tables with "open addressing" and "double hashing". - * Scopes can be nested; the next field of a scope points + * as hash tables. Scopes can be nested; the next field of a scope points * to its next outer scope. Nested scopes can share their hash tables. * *

This is NOT part of any supported API. @@ -68,7 +67,6 @@ public Entry elems; /** The number of elements in this scope. - * This includes deleted elements, whose value is the sentinel. */ public int nelems = 0; @@ -111,8 +109,7 @@ } } - /** Use as a "not-found" result for lookup. - * Also used to mark deleted entries in the table. + /** Every hash bucket is a list of Entry's which ends in sentinel. */ private static final Entry sentinel = new Entry(null, null, null, null); @@ -133,15 +130,12 @@ this.owner = owner; this.table = table; this.hashMask = table.length - 1; + this.elems = null; + this.nelems = 0; + this.shared = 0; this.scopeCounter = scopeCounter; } - /** Convenience constructor used for dup and dupUnshared. */ - private Scope(Scope next, Symbol owner, Entry[] table) { - this(next, owner, table, next.scopeCounter); - this.nelems = next.nelems; - } - /** Construct a new scope, within scope next, with given owner, * using a fresh table of length INITIAL_SIZE. */ @@ -151,6 +145,7 @@ protected Scope(Symbol owner, ScopeCounter scopeCounter) { this(null, owner, new Entry[INITIAL_SIZE], scopeCounter); + for (int i = 0; i < INITIAL_SIZE; i++) table[i] = sentinel; } /** Construct a fresh scope within this scope, with same owner, @@ -159,7 +154,11 @@ * of fresh tables. */ public Scope dup() { - return dup(this.owner); + Scope result = new Scope(this, this.owner, this.table, scopeCounter); + shared++; + // System.out.println("====> duping scope " + this.hashCode() + " owned by " + this.owner + " to " + result.hashCode()); + // new Error().printStackTrace(System.out); + return result; } /** Construct a fresh scope within this scope, with new owner, @@ -168,7 +167,7 @@ * of fresh tables. */ public Scope dup(Symbol newOwner) { - Scope result = new Scope(this, newOwner, this.table); + Scope result = new Scope(this, newOwner, this.table, scopeCounter); shared++; // System.out.println("====> duping scope " + this.hashCode() + " owned by " + newOwner + " to " + result.hashCode()); // new Error().printStackTrace(System.out); @@ -180,7 +179,7 @@ * the table of its outer scope. */ public Scope dupUnshared() { - return new Scope(this, this.owner, this.table.clone()); + return new Scope(this, this.owner, this.table.clone(), scopeCounter); } /** Remove all entries of this scope from its table, if shared @@ -190,7 +189,7 @@ assert shared == 0; if (table != next.table) return next; while (elems != null) { - int hash = getIndex(elems.sym.name); + int hash = elems.sym.name.hashCode() & hashMask; Entry e = table[hash]; assert e == elems : elems.sym; table[hash] = elems.shadowed; @@ -198,7 +197,6 @@ } assert next.shared > 0; next.shared--; - next.nelems = nelems; // System.out.println("====> leaving scope " + this.hashCode() + " owned by " + this.owner + " to " + next.hashCode()); // new Error().printStackTrace(System.out); return next; @@ -217,17 +215,19 @@ s.hashMask = newtable.length - 1; } } - int n = 0; - for (int i = oldtable.length; --i >= 0; ) { - Entry e = oldtable[i]; - if (e != null && e != sentinel) { - table[getIndex(e.sym.name)] = e; - n++; - } + for (int i = 0; i < newtable.length; i++) newtable[i] = sentinel; + for (int i = 0; i < oldtable.length; i++) copy(oldtable[i]); + } + + /** Copy the given entry and all entries shadowed by it to table + */ + private void copy(Entry e) { + if (e.sym != null) { + copy(e.shadowed); + int hash = e.sym.name.hashCode() & hashMask; + e.shadowed = table[hash]; + table[hash] = e; } - // We don't need to update nelems for shared inherited scopes, - // since that gets handled by leave(). - nelems = n; } /** Enter symbol sym in this scope. @@ -248,17 +248,13 @@ */ public void enter(Symbol sym, Scope s, Scope origin) { assert shared == 0; - if (nelems * 3 >= hashMask * 2) - dble(); - int hash = getIndex(sym.name); - Entry old = table[hash]; - if (old == null) { - old = sentinel; - nelems++; - } - Entry e = makeEntry(sym, old, elems, s, origin); + // Temporarily disabled (bug 6460352): + // if (nelems * 3 >= hashMask * 2) dble(); + int hash = sym.name.hashCode() & hashMask; + Entry e = makeEntry(sym, table[hash], elems, s, origin); table[hash] = e; elems = e; + nelems++; scopeCounter.inc(); } @@ -272,15 +268,15 @@ public void remove(Symbol sym) { assert shared == 0; Entry e = lookup(sym.name); + while (e.scope == this && e.sym != sym) e = e.next(); if (e.scope == null) return; scopeCounter.inc(); // remove e from table and shadowed list; - int i = getIndex(sym.name); - Entry te = table[i]; + Entry te = table[sym.name.hashCode() & hashMask]; if (te == e) - table[i] = e.shadowed; + table[sym.name.hashCode() & hashMask] = e.shadowed; else while (true) { if (te.shadowed == e) { te.shadowed = e.shadowed; @@ -339,50 +335,12 @@ return lookup(name, noFilter); } public Entry lookup(Name name, Filter sf) { - Entry e = table[getIndex(name)]; - if (e == null || e == sentinel) - return sentinel; + Entry e = table[name.hashCode() & hashMask]; while (e.scope != null && (e.sym.name != name || !sf.accepts(e.sym))) e = e.shadowed; return e; } - /*void dump (java.io.PrintStream out) { - out.println(this); - for (int l=0; l < table.length; l++) { - Entry le = table[l]; - out.print("#"+l+": "); - if (le==sentinel) out.println("sentinel"); - else if(le == null) out.println("null"); - else out.println(""+le+" s:"+le.sym); - } - }*/ - - /** Look for slot in the table. - * We use open addressing with double hashing. - */ - int getIndex (Name name) { - int h = name.hashCode(); - int i = h & hashMask; - // The expression below is always odd, so it is guaranteed - // be be mutually prime with table.length, a power of 2. - int x = hashMask - ((h + (h >> 16)) << 1); - int d = -1; // Index of a deleted item. - for (;;) { - Entry e = table[i]; - if (e == null) - return d >= 0 ? d : i; - if (e == sentinel) { - // We have to keep searching even if we see a deleted item. - // However, remember the index in case we fail to find the name. - if (d < 0) - d = i; - } else if (e.sym.name == name) - return i; - i = (i + x) & hashMask; - } - } - public Iterable getElements() { return getElements(noFilter); } @@ -512,11 +470,10 @@ } public Entry lookup(Name name) { - Entry e = table[getIndex(name)]; - if (e == null) - return sentinel; + Entry e = table[name.hashCode() & hashMask]; while (e.scope != null && - (/* Since an inner class will show up in package and + (e.sym.name != name || + /* Since an inner class will show up in package and * import scopes until its inner class attribute has * been processed, we have to weed it out here. This * is done by comparing the owners of the entry's