langtools/src/share/classes/com/sun/tools/javac/code/Scope.java
changeset 8242 3873b4aaf4a8
parent 8032 e1aa25ccdabb
child 8427 703181b01773
equal deleted inserted replaced
8241:4161b56e0d20 8242:3873b4aaf4a8
    70     /** The number of elements in this scope.
    70     /** The number of elements in this scope.
    71      * This includes deleted elements, whose value is the sentinel.
    71      * This includes deleted elements, whose value is the sentinel.
    72      */
    72      */
    73     int nelems = 0;
    73     int nelems = 0;
    74 
    74 
    75     /** A timestamp - useful to quickly check whether a scope has changed or not
       
    76      */
       
    77     public ScopeCounter scopeCounter;
       
    78 
       
    79     static ScopeCounter dummyCounter = new ScopeCounter() {
       
    80         @Override
       
    81         public void inc() {
       
    82             //do nothing
       
    83         }
       
    84     };
       
    85 
       
    86     /** A list of scopes to be notified if items are to be removed from this scope.
    75     /** A list of scopes to be notified if items are to be removed from this scope.
    87      */
    76      */
    88     List<Scope> listeners = List.nil();
    77     List<Scope> listeners = List.nil();
    89 
       
    90     public static class ScopeCounter {
       
    91         protected static final Context.Key<ScopeCounter> scopeCounterKey =
       
    92             new Context.Key<ScopeCounter>();
       
    93 
       
    94         public static ScopeCounter instance(Context context) {
       
    95             ScopeCounter instance = context.get(scopeCounterKey);
       
    96             if (instance == null)
       
    97                 instance = new ScopeCounter(context);
       
    98             return instance;
       
    99         }
       
   100 
       
   101         protected ScopeCounter(Context context) {
       
   102             context.put(scopeCounterKey, this);
       
   103         }
       
   104 
       
   105         private ScopeCounter() {};
       
   106 
       
   107         private long val = 0;
       
   108 
       
   109         public void inc() {
       
   110             val++;
       
   111         }
       
   112 
       
   113         public long val() {
       
   114             return val;
       
   115         }
       
   116     }
       
   117 
    78 
   118     /** Use as a "not-found" result for lookup.
    79     /** Use as a "not-found" result for lookup.
   119      * Also used to mark deleted entries in the table.
    80      * Also used to mark deleted entries in the table.
   120      */
    81      */
   121     private static final Entry sentinel = new Entry(null, null, null, null);
    82     private static final Entry sentinel = new Entry(null, null, null, null);
   124      */
    85      */
   125     private static final int INITIAL_SIZE = 0x10;
    86     private static final int INITIAL_SIZE = 0x10;
   126 
    87 
   127     /** A value for the empty scope.
    88     /** A value for the empty scope.
   128      */
    89      */
   129     public static final Scope emptyScope = new Scope(null, null, new Entry[]{}, dummyCounter);
    90     public static final Scope emptyScope = new Scope(null, null, new Entry[]{});
   130 
    91 
   131     /** Construct a new scope, within scope next, with given owner, using
    92     /** Construct a new scope, within scope next, with given owner, using
   132      *  given table. The table's length must be an exponent of 2.
    93      *  given table. The table's length must be an exponent of 2.
   133      */
    94      */
   134     private Scope(Scope next, Symbol owner, Entry[] table, ScopeCounter scopeCounter) {
    95     private Scope(Scope next, Symbol owner, Entry[] table) {
   135         this.next = next;
    96         this.next = next;
   136         Assert.check(emptyScope == null || owner != null);
    97         Assert.check(emptyScope == null || owner != null);
   137         this.owner = owner;
    98         this.owner = owner;
   138         this.table = table;
    99         this.table = table;
   139         this.hashMask = table.length - 1;
   100         this.hashMask = table.length - 1;
   140         this.scopeCounter = scopeCounter;
       
   141     }
   101     }
   142 
   102 
   143     /** Convenience constructor used for dup and dupUnshared. */
   103     /** Convenience constructor used for dup and dupUnshared. */
   144     private Scope(Scope next, Symbol owner, Entry[] table) {
   104     private Scope(Scope next, Symbol owner, Entry[] table, int nelems) {
   145         this(next, owner, table, next.scopeCounter);
   105         this(next, owner, table);
   146         this.nelems = next.nelems;
   106         this.nelems = nelems;
   147     }
   107     }
   148 
   108 
   149     /** Construct a new scope, within scope next, with given owner,
   109     /** Construct a new scope, within scope next, with given owner,
   150      *  using a fresh table of length INITIAL_SIZE.
   110      *  using a fresh table of length INITIAL_SIZE.
   151      */
   111      */
   152     public Scope(Symbol owner) {
   112     public Scope(Symbol owner) {
   153         this(owner, dummyCounter);
   113         this(null, owner, new Entry[INITIAL_SIZE]);
   154     }
       
   155 
       
   156     protected Scope(Symbol owner, ScopeCounter scopeCounter) {
       
   157         this(null, owner, new Entry[INITIAL_SIZE], scopeCounter);
       
   158     }
   114     }
   159 
   115 
   160     /** Construct a fresh scope within this scope, with same owner,
   116     /** Construct a fresh scope within this scope, with same owner,
   161      *  which shares its table with the outer scope. Used in connection with
   117      *  which shares its table with the outer scope. Used in connection with
   162      *  method leave if scope access is stack-like in order to avoid allocation
   118      *  method leave if scope access is stack-like in order to avoid allocation
   170      *  which shares its table with the outer scope. Used in connection with
   126      *  which shares its table with the outer scope. Used in connection with
   171      *  method leave if scope access is stack-like in order to avoid allocation
   127      *  method leave if scope access is stack-like in order to avoid allocation
   172      *  of fresh tables.
   128      *  of fresh tables.
   173      */
   129      */
   174     public Scope dup(Symbol newOwner) {
   130     public Scope dup(Symbol newOwner) {
   175         Scope result = new Scope(this, newOwner, this.table);
   131         Scope result = new Scope(this, newOwner, this.table, this.nelems);
   176         shared++;
   132         shared++;
   177         // System.out.println("====> duping scope " + this.hashCode() + " owned by " + newOwner + " to " + result.hashCode());
   133         // System.out.println("====> duping scope " + this.hashCode() + " owned by " + newOwner + " to " + result.hashCode());
   178         // new Error().printStackTrace(System.out);
   134         // new Error().printStackTrace(System.out);
   179         return result;
   135         return result;
   180     }
   136     }
   182     /** Construct a fresh scope within this scope, with same owner,
   138     /** Construct a fresh scope within this scope, with same owner,
   183      *  with a new hash table, whose contents initially are those of
   139      *  with a new hash table, whose contents initially are those of
   184      *  the table of its outer scope.
   140      *  the table of its outer scope.
   185      */
   141      */
   186     public Scope dupUnshared() {
   142     public Scope dupUnshared() {
   187         return new Scope(this, this.owner, this.table.clone());
   143         return new Scope(this, this.owner, this.table.clone(), this.nelems);
   188     }
   144     }
   189 
   145 
   190     /** Remove all entries of this scope from its table, if shared
   146     /** Remove all entries of this scope from its table, if shared
   191      *  with next.
   147      *  with next.
   192      */
   148      */
   261             nelems++;
   217             nelems++;
   262         }
   218         }
   263         Entry e = makeEntry(sym, old, elems, s, origin);
   219         Entry e = makeEntry(sym, old, elems, s, origin);
   264         table[hash] = e;
   220         table[hash] = e;
   265         elems = e;
   221         elems = e;
   266         scopeCounter.inc();
       
   267     }
   222     }
   268 
   223 
   269     Entry makeEntry(Symbol sym, Entry shadowed, Entry sibling, Scope scope, Scope origin) {
   224     Entry makeEntry(Symbol sym, Entry shadowed, Entry sibling, Scope scope, Scope origin) {
   270         return new Entry(sym, shadowed, sibling, scope);
   225         return new Entry(sym, shadowed, sibling, scope);
   271     }
   226     }
   275      */
   230      */
   276     public void remove(Symbol sym) {
   231     public void remove(Symbol sym) {
   277         Assert.check(shared == 0);
   232         Assert.check(shared == 0);
   278         Entry e = lookup(sym.name);
   233         Entry e = lookup(sym.name);
   279         if (e.scope == null) return;
   234         if (e.scope == null) return;
   280 
       
   281         scopeCounter.inc();
       
   282 
   235 
   283         // remove e from table and shadowed list;
   236         // remove e from table and shadowed list;
   284         int i = getIndex(sym.name);
   237         int i = getIndex(sym.name);
   285         Entry te = table[i];
   238         Entry te = table[i];
   286         if (te == e)
   239         if (te == e)
   557     public static class DelegatedScope extends Scope {
   510     public static class DelegatedScope extends Scope {
   558         Scope delegatee;
   511         Scope delegatee;
   559         public static final Entry[] emptyTable = new Entry[0];
   512         public static final Entry[] emptyTable = new Entry[0];
   560 
   513 
   561         public DelegatedScope(Scope outer) {
   514         public DelegatedScope(Scope outer) {
   562             super(outer, outer.owner, emptyTable, outer.scopeCounter);
   515             super(outer, outer.owner, emptyTable);
   563             delegatee = outer;
   516             delegatee = outer;
   564         }
   517         }
   565         public Scope dup() {
   518         public Scope dup() {
   566             return new DelegatedScope(next);
   519             return new DelegatedScope(next);
   567         }
   520         }
   580         public void remove(Symbol sym) {
   533         public void remove(Symbol sym) {
   581             throw new AssertionError(sym);
   534             throw new AssertionError(sym);
   582         }
   535         }
   583         public Entry lookup(Name name) {
   536         public Entry lookup(Name name) {
   584             return delegatee.lookup(name);
   537             return delegatee.lookup(name);
   585         }
       
   586     }
       
   587 
       
   588     /** A class scope, for which a scope counter should be provided */
       
   589     public static class ClassScope extends Scope {
       
   590 
       
   591         ClassScope(Scope next, Symbol owner, Entry[] table, ScopeCounter scopeCounter) {
       
   592             super(next, owner, table, scopeCounter);
       
   593         }
       
   594 
       
   595         public ClassScope(Symbol owner, ScopeCounter scopeCounter) {
       
   596             super(owner, scopeCounter);
       
   597         }
   538         }
   598     }
   539     }
   599 
   540 
   600     /** An error scope, for which the owner should be an error symbol. */
   541     /** An error scope, for which the owner should be an error symbol. */
   601     public static class ErrorScope extends Scope {
   542     public static class ErrorScope extends Scope {
   602         ErrorScope(Scope next, Symbol errSymbol, Entry[] table) {
   543         ErrorScope(Scope next, Symbol errSymbol, Entry[] table) {
   603             super(next, /*owner=*/errSymbol, table, dummyCounter);
   544             super(next, /*owner=*/errSymbol, table);
   604         }
   545         }
   605         public ErrorScope(Symbol errSymbol) {
   546         public ErrorScope(Symbol errSymbol) {
   606             super(errSymbol);
   547             super(errSymbol);
   607         }
   548         }
   608         public Scope dup() {
   549         public Scope dup() {