src/share/classes/com/sun/tools/javac/code/Scope.java

changeset 688
50f9ac2f4730
parent 673
7ae4016c5938
child 725
601160d857ef
equal deleted inserted replaced
683:bbc9765d9ec6 688:50f9ac2f4730
68 68
69 /** The number of elements in this scope. 69 /** The number of elements in this scope.
70 */ 70 */
71 public int nelems = 0; 71 public int nelems = 0;
72 72
73 /** A timestamp - useful to quickly check whether a scope has changed or not
74 */
75 public ScopeCounter scopeCounter;
76
77 static ScopeCounter dummyCounter = new ScopeCounter() {
78 @Override
79 public void inc() {
80 //do nothing
81 }
82 };
83
84 public static class ScopeCounter {
85 protected static final Context.Key<ScopeCounter> scopeCounterKey =
86 new Context.Key<ScopeCounter>();
87
88 public static ScopeCounter instance(Context context) {
89 ScopeCounter instance = context.get(scopeCounterKey);
90 if (instance == null)
91 instance = new ScopeCounter(context);
92 return instance;
93 }
94
95 protected ScopeCounter(Context context) {
96 context.put(scopeCounterKey, this);
97 }
98
99 private ScopeCounter() {};
100
101 private long val = 0;
102
103 public void inc() {
104 val++;
105 }
106
107 public long val() {
108 return val;
109 }
110 }
111
73 /** Every hash bucket is a list of Entry's which ends in sentinel. 112 /** Every hash bucket is a list of Entry's which ends in sentinel.
74 */ 113 */
75 private static final Entry sentinel = new Entry(null, null, null, null); 114 private static final Entry sentinel = new Entry(null, null, null, null);
76 115
77 /** The hash table's initial size. 116 /** The hash table's initial size.
78 */ 117 */
79 private static final int INITIAL_SIZE = 0x10; 118 private static final int INITIAL_SIZE = 0x10;
80 119
81 /** A value for the empty scope. 120 /** A value for the empty scope.
82 */ 121 */
83 public static final Scope emptyScope = new Scope(null, null, new Entry[]{}); 122 public static final Scope emptyScope = new Scope(null, null, new Entry[]{}, dummyCounter);
84 123
85 /** Construct a new scope, within scope next, with given owner, using 124 /** Construct a new scope, within scope next, with given owner, using
86 * given table. The table's length must be an exponent of 2. 125 * given table. The table's length must be an exponent of 2.
87 */ 126 */
88 Scope(Scope next, Symbol owner, Entry[] table) { 127 private Scope(Scope next, Symbol owner, Entry[] table, ScopeCounter scopeCounter) {
89 this.next = next; 128 this.next = next;
90 assert emptyScope == null || owner != null; 129 assert emptyScope == null || owner != null;
91 this.owner = owner; 130 this.owner = owner;
92 this.table = table; 131 this.table = table;
93 this.hashMask = table.length - 1; 132 this.hashMask = table.length - 1;
94 this.elems = null; 133 this.elems = null;
95 this.nelems = 0; 134 this.nelems = 0;
96 this.shared = 0; 135 this.shared = 0;
136 this.scopeCounter = scopeCounter;
97 } 137 }
98 138
99 /** Construct a new scope, within scope next, with given owner, 139 /** Construct a new scope, within scope next, with given owner,
100 * using a fresh table of length INITIAL_SIZE. 140 * using a fresh table of length INITIAL_SIZE.
101 */ 141 */
102 public Scope(Symbol owner) { 142 public Scope(Symbol owner) {
103 this(null, owner, new Entry[INITIAL_SIZE]); 143 this(owner, dummyCounter);
144 }
145
146 protected Scope(Symbol owner, ScopeCounter scopeCounter) {
147 this(null, owner, new Entry[INITIAL_SIZE], scopeCounter);
104 for (int i = 0; i < INITIAL_SIZE; i++) table[i] = sentinel; 148 for (int i = 0; i < INITIAL_SIZE; i++) table[i] = sentinel;
105 } 149 }
106 150
107 /** Construct a fresh scope within this scope, with same owner, 151 /** Construct a fresh scope within this scope, with same owner,
108 * which shares its table with the outer scope. Used in connection with 152 * which shares its table with the outer scope. Used in connection with
109 * method leave if scope access is stack-like in order to avoid allocation 153 * method leave if scope access is stack-like in order to avoid allocation
110 * of fresh tables. 154 * of fresh tables.
111 */ 155 */
112 public Scope dup() { 156 public Scope dup() {
113 Scope result = new Scope(this, this.owner, this.table); 157 Scope result = new Scope(this, this.owner, this.table, scopeCounter);
114 shared++; 158 shared++;
115 // System.out.println("====> duping scope " + this.hashCode() + " owned by " + this.owner + " to " + result.hashCode()); 159 // System.out.println("====> duping scope " + this.hashCode() + " owned by " + this.owner + " to " + result.hashCode());
116 // new Error().printStackTrace(System.out); 160 // new Error().printStackTrace(System.out);
117 return result; 161 return result;
118 } 162 }
121 * which shares its table with the outer scope. Used in connection with 165 * which shares its table with the outer scope. Used in connection with
122 * method leave if scope access is stack-like in order to avoid allocation 166 * method leave if scope access is stack-like in order to avoid allocation
123 * of fresh tables. 167 * of fresh tables.
124 */ 168 */
125 public Scope dup(Symbol newOwner) { 169 public Scope dup(Symbol newOwner) {
126 Scope result = new Scope(this, newOwner, this.table); 170 Scope result = new Scope(this, newOwner, this.table, scopeCounter);
127 shared++; 171 shared++;
128 // System.out.println("====> duping scope " + this.hashCode() + " owned by " + newOwner + " to " + result.hashCode()); 172 // System.out.println("====> duping scope " + this.hashCode() + " owned by " + newOwner + " to " + result.hashCode());
129 // new Error().printStackTrace(System.out); 173 // new Error().printStackTrace(System.out);
130 return result; 174 return result;
131 } 175 }
133 /** Construct a fresh scope within this scope, with same owner, 177 /** Construct a fresh scope within this scope, with same owner,
134 * with a new hash table, whose contents initially are those of 178 * with a new hash table, whose contents initially are those of
135 * the table of its outer scope. 179 * the table of its outer scope.
136 */ 180 */
137 public Scope dupUnshared() { 181 public Scope dupUnshared() {
138 return new Scope(this, this.owner, this.table.clone()); 182 return new Scope(this, this.owner, this.table.clone(), scopeCounter);
139 } 183 }
140 184
141 /** Remove all entries of this scope from its table, if shared 185 /** Remove all entries of this scope from its table, if shared
142 * with next. 186 * with next.
143 */ 187 */
209 int hash = sym.name.hashCode() & hashMask; 253 int hash = sym.name.hashCode() & hashMask;
210 Entry e = makeEntry(sym, table[hash], elems, s, origin); 254 Entry e = makeEntry(sym, table[hash], elems, s, origin);
211 table[hash] = e; 255 table[hash] = e;
212 elems = e; 256 elems = e;
213 nelems++; 257 nelems++;
258 scopeCounter.inc();
214 } 259 }
215 260
216 Entry makeEntry(Symbol sym, Entry shadowed, Entry sibling, Scope scope, Scope origin) { 261 Entry makeEntry(Symbol sym, Entry shadowed, Entry sibling, Scope scope, Scope origin) {
217 return new Entry(sym, shadowed, sibling, scope); 262 return new Entry(sym, shadowed, sibling, scope);
218 } 263 }
223 public void remove(Symbol sym) { 268 public void remove(Symbol sym) {
224 assert shared == 0; 269 assert shared == 0;
225 Entry e = lookup(sym.name); 270 Entry e = lookup(sym.name);
226 while (e.scope == this && e.sym != sym) e = e.next(); 271 while (e.scope == this && e.sym != sym) e = e.next();
227 if (e.scope == null) return; 272 if (e.scope == null) return;
273
274 scopeCounter.inc();
228 275
229 // remove e from table and shadowed list; 276 // remove e from table and shadowed list;
230 Entry te = table[sym.name.hashCode() & hashMask]; 277 Entry te = table[sym.name.hashCode() & hashMask];
231 if (te == e) 278 if (te == e)
232 table[sym.name.hashCode() & hashMask] = e.shadowed; 279 table[sym.name.hashCode() & hashMask] = e.shadowed;
470 public static class DelegatedScope extends Scope { 517 public static class DelegatedScope extends Scope {
471 Scope delegatee; 518 Scope delegatee;
472 public static final Entry[] emptyTable = new Entry[0]; 519 public static final Entry[] emptyTable = new Entry[0];
473 520
474 public DelegatedScope(Scope outer) { 521 public DelegatedScope(Scope outer) {
475 super(outer, outer.owner, emptyTable); 522 super(outer, outer.owner, emptyTable, outer.scopeCounter);
476 delegatee = outer; 523 delegatee = outer;
477 } 524 }
478 public Scope dup() { 525 public Scope dup() {
479 return new DelegatedScope(next); 526 return new DelegatedScope(next);
480 } 527 }
493 public void remove(Symbol sym) { 540 public void remove(Symbol sym) {
494 throw new AssertionError(sym); 541 throw new AssertionError(sym);
495 } 542 }
496 public Entry lookup(Name name) { 543 public Entry lookup(Name name) {
497 return delegatee.lookup(name); 544 return delegatee.lookup(name);
545 }
546 }
547
548 /** A class scope, for which a scope counter should be provided */
549 public static class ClassScope extends Scope {
550
551 ClassScope(Scope next, Symbol owner, Entry[] table, ScopeCounter scopeCounter) {
552 super(next, owner, table, scopeCounter);
553 }
554
555 public ClassScope(Symbol owner, ScopeCounter scopeCounter) {
556 super(owner, scopeCounter);
498 } 557 }
499 } 558 }
500 559
501 /** An error scope, for which the owner should be an error symbol. */ 560 /** An error scope, for which the owner should be an error symbol. */
502 public static class ErrorScope extends Scope { 561 public static class ErrorScope extends Scope {
503 ErrorScope(Scope next, Symbol errSymbol, Entry[] table) { 562 ErrorScope(Scope next, Symbol errSymbol, Entry[] table) {
504 super(next, /*owner=*/errSymbol, table); 563 super(next, /*owner=*/errSymbol, table, dummyCounter);
505 } 564 }
506 public ErrorScope(Symbol errSymbol) { 565 public ErrorScope(Symbol errSymbol) {
507 super(errSymbol); 566 super(errSymbol);
508 } 567 }
509 public Scope dup() { 568 public Scope dup() {

mercurial