/* * ConstantPool.java 1.9 02/09/27 SMI * * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved. * * This software is the confidential and proprietary information of Sun * Microsystems, Inc. ("Confidential Information"). You shall not * disclose such Confidential Information and shall use it only in * accordance with the terms of the license agreement you entered into * with Sun. * * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING * THIS SOFTWARE OR ITS DERIVATIVES. * Use is subject to license terms. */ package components; import java.io.DataOutput; import java.io.DataInput; import java.util.Hashtable; import java.util.Vector; import java.util.Enumeration; import java.io.IOException; import java.io.PrintStream; import sun.misc.Compare; public class ConstantPool implements Compare { protected Hashtable h; // for "quick" lookup protected Vector t; // for enumeration in order protected int n; protected ConstantObject constants[]= null; protected boolean locked = false; public boolean impureConstants = false; public ConstantPool(){ h = new Hashtable( 500, 0.7f ); t = new Vector(); t.addElement(null ); // 0th element is string of length 0. n = 1; } /** * doCompare * * @param obj1 first object to compare. * @param obj2 second object to compare. * @return -1 if obj1 > obj2, 0 if obj1 == obj2, 1 if obj1 < obj2. */ public int doCompare( java.lang.Object o1, java.lang.Object o2) { ConstantObject obj1 = (ConstantObject) o1; ConstantObject obj2 = (ConstantObject) o2; if (obj1.ldcReferences < obj2.ldcReferences) { return 1; } else if (obj1.ldcReferences == obj2.ldcReferences) return 0; return -1; } public void doSort() { int count = 0; int nNew = 1; // Retrieve the ConstantObject array from the hashtable. Enumeration e = h.elements(); ConstantObject arr[] = new ConstantObject[h.size()]; while (e.hasMoreElements()) { arr[count]= (ConstantObject) e.nextElement(); count++; } // Sorting the ConstantObject with descending reference // count. sun.misc.Sort.quicksort(arr, this); t.removeAllElements(); t.addElement(null); for (int i = 0; i < arr.length; i++) { arr[i].index = nNew; nNew += arr[i].nSlots; t.addElement(arr[i]); for (int j =arr[i].nSlots; j > 1; j-- ) t.addElement( null ); // place holder } constants = null; } /** * Return the ConstantObject in constant table corresponding to * the given ConstantObject s. * Inserts s if it is not already there. * The index member of the returned value (which * may be the object s!) will be set to its index in our * table. There will be no element of index 0. */ public ConstantObject add( ConstantObject s ) { if ( s.shared && s.containingPool==this ) return s; // this is already it! ConstantObject r = (ConstantObject)h.get( s ); if ( r == null ){ if ( locked ){ throw new Error("add on locked ConstantPool"); } if ( s.shared ){ // already in another constant pool! // this copy is not deep enough!!! r = (ConstantObject) s.clone(); } else { r = s; } r.externalize( this ); // Deeper copy, as required. r.index = n; n += r.nSlots; r.shared = true; r.containingPool = this; h.put( r, r ); t.addElement( r ); for ( int i =r.nSlots; i > 1; i-- ) t.addElement( null ); // place holder. constants = null; // mark any "constants" as obsolete! } return r; } /* * Like add() above, but with less management: still * to ensure that there's only one entry like this in the pool, * but doesn't externalize/share. */ public ConstantObject appendElement( ConstantObject s ){ ConstantObject r = (ConstantObject)h.get( s ); if ( r == null ){ if ( locked ){ throw new Error("add on locked ConstantPool"); } r = s; r.index = n; n += r.nSlots; h.put( r, r ); t.addElement( r ); for ( int i =r.nSlots; i > 1; i-- ) t.addElement( null ); // place holder. constants = null; // mark any "constants" as obsolete! } else { r.ldcReferences += s.ldcReferences; r.references += s.references; } return r; } public ConstantObject dup( ConstantObject s ) { if ( s.shared && s.containingPool==this ) return s; return this.add( (ConstantObject) s.clone() ); } public ConstantObject[] getConstants(){ if ( constants != null ) return constants; constants = new ConstantObject[ t.size() ]; t.copyInto( constants ); return constants; } public Enumeration getEnumeration(){ return t.elements(); } public void lock(){ locked = true; } public void unlock(){ locked = false; } public int read( DataInput in ) throws IOException { int n = in.readUnsignedShort(); ConstantObject c[] = new ConstantObject[n]; for (int i = 1; i < n; i+=c[i].nSlots ){ c[i] = ConstantObject.readObject(in); } //System.err.println("DEBUG CONSTANTPOOL DUMP" ); //for (int i = 1; i < n; i+=c[i].nSlots ){ // System.err.println("\t#"+i+"\t"+c[i].toString() ); //} for (int i = 1; i < n; i+=c[i].nSlots ){ c[i].resolve( c ); } for (int i = 1; i < n; i+=c[i].nSlots ){ add( c[i] ); } constants = c; // a hack, but a valid one. return n; } public void clearAllReferences(){ ConstantObject c; for( int i=1; i< n; i+=c.nSlots){ c = (ConstantObject)t.elementAt(i); c.clearReference(); } } /* * If we are not loading entire classes, then there is * some chance that unreferenced constants have sneaked into * this pool. They can be deleted and the table made smaller. * This is a waste of time when partial class loading is not done. * * Naturally, we preserve the null entries. * */ public void smashConstantPool(){ int nNew = 1; ConstantObject o; // first, count and index. for ( int i = 1; i < n; i += o.nSlots ){ o = (ConstantObject)t.elementAt(i); if ( o.references == 0 ){ o.index = -1; h.remove( o ); } else { // we're keeping it. o.index = nNew; nNew += o.nSlots; } } if ( nNew == n ) return; // all done! // copy live ones from old vector to new. Vector newConstants = new Vector( nNew ); newConstants.addElement( null ); for ( int i = 1; i < n; i += o.nSlots ){ o = (ConstantObject)t.elementAt(i); if ( o.references != 0 ){ // we're keeping it. newConstants.addElement(o); for ( int j =o.nSlots; j > 1; j-- ) newConstants.addElement( null ); // place holder. } } t = newConstants; n = nNew; constants = null; // mark as obsolete } /** * Write out the number of constants to write. * Then write out the constants, in order. * Returns total number of constants written. */ public int write( DataOutput o ) throws IOException { o.writeShort(n); ConstantObject ob; for (int i = 1; i < n; i+=ob.nSlots ){ ob = (ConstantObject)t.elementAt(i); if ( ob != null ) ob.write(o); } return n; } public void dump( PrintStream o ){ ConstantObject c; for( int i=1; i< n; i+=c.nSlots){ c = (ConstantObject)t.elementAt(i); o.println("\t["+c.index+"]\t"+c.references+"\t"+c.toString() ); } } }