001    /*
002     * Copyright 1999-2008 Sun Microsystems, Inc.  All Rights Reserved.
003     * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004     *
005     * This code is free software; you can redistribute it and/or modify it
006     * under the terms of the GNU General Public License version 2 only, as
007     * published by the Free Software Foundation.  Sun designates this
008     * particular file as subject to the "Classpath" exception as provided
009     * by Sun in the LICENSE file that accompanied this code.
010     *
011     * This code is distributed in the hope that it will be useful, but WITHOUT
012     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013     * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014     * version 2 for more details (a copy is included in the LICENSE file that
015     * accompanied this code).
016     *
017     * You should have received a copy of the GNU General Public License version
018     * 2 along with this work; if not, write to the Free Software Foundation,
019     * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020     *
021     * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022     * CA 95054 USA or visit www.sun.com if you need additional information or
023     * have any questions.
024     */
025    
026    package com.sun.tools.javac.jvm;
027    
028    import java.util.*;
029    
030    import com.sun.tools.javac.code.Symbol.*;
031    
032    /** An internal structure that corresponds to the constant pool of a classfile.
033     *
034     *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
035     *  you write code that depends on this, you do so at your own risk.
036     *  This code and its internal interfaces are subject to change or
037     *  deletion without notice.</b>
038     */
039    public class Pool {
040    
041        public static final int MAX_ENTRIES = 0xFFFF;
042        public static final int MAX_STRING_LENGTH = 0xFFFF;
043    
044        /** Index of next constant to be entered.
045         */
046        int pp;
047    
048        /** The initial pool buffer.
049         */
050        Object[] pool;
051    
052        /** A hashtable containing all constants in the pool.
053         */
054        Map<Object,Integer> indices;
055    
056        /** Construct a pool with given number of elements and element array.
057         */
058        public Pool(int pp, Object[] pool) {
059            this.pp = pp;
060            this.pool = pool;
061            this.indices = new HashMap<Object,Integer>(pool.length);
062            for (int i = 1; i < pp; i++) {
063                if (pool[i] != null) indices.put(pool[i], i);
064            }
065        }
066    
067        /** Construct an empty pool.
068         */
069        public Pool() {
070            this(1, new Object[64]);
071        }
072    
073        /** Return the number of entries in the constant pool.
074         */
075        public int numEntries() {
076            return pp;
077        }
078    
079        /** Remove everything from this pool.
080         */
081        public void reset() {
082            pp = 1;
083            indices.clear();
084        }
085    
086        /** Double pool buffer in size.
087         */
088        private void doublePool() {
089            Object[] newpool = new Object[pool.length * 2];
090            System.arraycopy(pool, 0, newpool, 0, pool.length);
091            pool = newpool;
092        }
093    
094        /** Place an object in the pool, unless it is already there.
095         *  If object is a symbol also enter its owner unless the owner is a
096         *  package.  Return the object's index in the pool.
097         */
098        public int put(Object value) {
099            if (value instanceof MethodSymbol)
100                value = new Method((MethodSymbol)value);
101            else if (value instanceof VarSymbol)
102                value = new Variable((VarSymbol)value);
103    //      assert !(value instanceof Type.TypeVar);
104            Integer index = indices.get(value);
105            if (index == null) {
106    //          System.err.println("put " + value + " " + value.getClass());//DEBUG
107                index = pp;
108                indices.put(value, index);
109                if (pp == pool.length) doublePool();
110                pool[pp++] = value;
111                if (value instanceof Long || value instanceof Double) {
112                    if (pp == pool.length) doublePool();
113                    pool[pp++] = null;
114                }
115            }
116            return index.intValue();
117        }
118    
119        /** Return the given object's index in the pool,
120         *  or -1 if object is not in there.
121         */
122        public int get(Object o) {
123            Integer n = indices.get(o);
124            return n == null ? -1 : n.intValue();
125        }
126    
127        static class Method extends DelegatedSymbol {
128            MethodSymbol m;
129            Method(MethodSymbol m) {
130                super(m);
131                this.m = m;
132            }
133            public boolean equals(Object other) {
134                if (!(other instanceof Method)) return false;
135                MethodSymbol o = ((Method)other).m;
136                return
137                    o.name == m.name &&
138                    o.owner == m.owner &&
139                    o.type.equals(m.type);
140            }
141            public int hashCode() {
142                return
143                    m.name.hashCode() * 33 +
144                    m.owner.hashCode() * 9 +
145                    m.type.hashCode();
146            }
147        }
148    
149        static class Variable extends DelegatedSymbol {
150            VarSymbol v;
151            Variable(VarSymbol v) {
152                super(v);
153                this.v = v;
154            }
155            public boolean equals(Object other) {
156                if (!(other instanceof Variable)) return false;
157                VarSymbol o = ((Variable)other).v;
158                return
159                    o.name == v.name &&
160                    o.owner == v.owner &&
161                    o.type.equals(v.type);
162            }
163            public int hashCode() {
164                return
165                    v.name.hashCode() * 33 +
166                    v.owner.hashCode() * 9 +
167                    v.type.hashCode();
168            }
169        }
170    }