/*
* @(#)CVMSigForm.java 1.13 06/10/10
*
* Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 only, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License version 2 for more details (a copy is
* included at /legal/license.txt).
*
* You should have received a copy of the GNU General Public License
* version 2 along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 or visit www.sun.com if you need additional
* information or have any questions.
*
*/
package vm;
/*
* A "form" is the same as a terse signature.
* It allows sharing of parts of method signatures,
* as well as facilitating JNI parameter passing.
*/
public
class CVMSigForm {
/* instance data is all public for printing purposes */
public CVMSigForm hashNext; // hash chain
public CVMSigForm listNext; // enumeration chain
public int nSyllables;
public int data[];
public int listNo;
public int entryNo;
/* static data, public for same reason */
// the two hash tables we use to look these things up.
// the first is for instances for which data.length==1
// the second is for all others.
public final static int NSINGLETONHASH = 100;
public static CVMSigForm singletonHash[] = new CVMSigForm[NSINGLETONHASH];
public final static int NBIGHASH = 1;
public static CVMSigForm bigHash[] = new CVMSigForm[NBIGHASH];
public final static int SYLLABLESPERDATUM= 8;
// the multiple lists of forms,
// which is how the writer would just as soon see them.
// make sure to call "enumerate" to fill in formNo.
public static CVMSigForm formList[] = new CVMSigForm[2];
public static int listLength[] = new int[2];
// for computing the "formNo", we assume that if data.length==1,
// a form takes a single slot. Then for each wordSizeIncrement additional
// words (or parts thereof), we allocate an additional slot.
// It would be nice if we had target-system information (such as
// the size of the structs we're union-ing with) at this point,
// but we don't so make some assumptions.
static int wordSizeIncrement = 3;
// statistics
static int nSingletonForms = 0;
static int nBigForms = 0;
/* constructor and constructor-related */
private CVMSigForm( int nSyl, int datawords[] ){
nSyllables = nSyl;
// COPY the data, as it is probably in a reusable temporary
// buffer
data = new int[ (nSyl+SYLLABLESPERDATUM-1) / SYLLABLESPERDATUM ];
System.arraycopy( datawords, 0, data, 0, data.length );
enlist( this );
}
private static synchronized void enlist( CVMSigForm thing ){
int listNo = thing.nSlots()-1;
if ( formList.length <= listNo ){
CVMSigForm newList[] = new CVMSigForm[ listNo+1 ];
System.arraycopy( formList, 0, newList, 0, formList.length );
formList = newList;
int newLength[] = new int[ listNo+1 ];
System.arraycopy( listLength, 0, newLength, 0, listLength.length );
listLength = newLength;
}
thing.listNext = formList[listNo];
formList[listNo] = thing;
listLength[listNo] += 1;
thing.listNo = listNo;
}
/* instance methods */
public int
nSlots() {
int nDataWords = (this.nSyllables+SYLLABLESPERDATUM-1) / SYLLABLESPERDATUM;
return nDataWords;
}
/* static methods */
public static void setWordSizeIncrement( int n ){
wordSizeIncrement = n;
}
public static CVMSigForm lookup( int nSyl, int d[] ){
int hashbucket;
CVMSigForm hashTable[];
CVMSigForm f;
/*
* If we cared more about performance, we'd specialize
* the singleton search further. For now, just get it right!
*/
if ( nSyl <= SYLLABLESPERDATUM ){
hashbucket = (int)(((long)d[0]&0xffffffffL) % NSINGLETONHASH);
hashTable = singletonHash;
} else {
hashbucket = 0; // kill me.
hashTable = bigHash;
}
searchloop:
for ( f = hashTable[hashbucket]; f != null; f = f.hashNext ){
if ( f.nSyllables != nSyl ) continue;
for ( int i = 0; i < f.data.length; i++ ){
if ( f.data[i] != d[i] ){
continue searchloop;
}
}
// found it!
return f;
}
// fell out of the loop because it wasn't there.
// put it there.
f = new CVMSigForm( nSyl, d );
f.hashNext = hashTable[hashbucket];
hashTable[hashbucket] = f;
if ( nSyl <= SYLLABLESPERDATUM ){
nSingletonForms += 1;
} else {
nBigForms += 1;
}
return f;
}
}