/*
* @(#)CVMMethodType.java 1.14 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;
import java.util.Vector;
/*
* Representation of signatures.
* They're little numbers, which are indices into
* a table.
*/
/*
* CVM has a complex scheme for representing types as 16-bit
* cookies. This code mimics the run-time code and thus builds the
* corresponding data structures, to be ROMed.
*/
public
class CVMMethodType implements CVMTypeCode, util.ClassFileConst {
/* instance fields */
public int entryNo = -1;
public CVMMethodType next; // hash chain
public CVMSigForm form;
public int nDetails;
public int details[]; // array of scalar-type cookies.
public int detailOffset; // for use by writer.
public CVMMethodType listNext; // for variety management.
/* static fields */
public static Vector methodTypes = new Vector();
/*
* When you change this, also change the constant NMETHODTYPEHASH
* in typeid_impl.h
*/
public final static int NHASH = 13*37; // arbitrary number, contains no 2
public static CVMMethodType hashTable[] = new CVMMethodType[ NHASH ];
/* constructor */
CVMMethodType( CVMSigForm f, int nd, int d[] ){
form = f;
nDetails = nd;
// COPY the data, as it is probably in a reusable temporary
// buffer
details = new int[ nd ];
System.arraycopy( d, 0, details, 0, nd );
synchronized( methodTypes ){
methodTypes.addElement( this );
}
}
/* static methods */
private static CVMMethodType
lookup( CVMSigForm f, int nd, int d[] ){
int hashBucket = (int)(((long)((f.data[0]<<16) + (nd>0?d[0]:0))&0xffffffffL) % NHASH);
CVMMethodType mt;
searchloop:
for ( mt = hashTable[hashBucket]; mt != null; mt = mt.next ){
if ( mt.form != f ) continue;
for ( int i = 0; i < nd; i++ ){
if ( mt.details[i] != d[i] ){
continue searchloop;
}
}
// found one.
return mt;
}
/* not in table */
mt = new CVMMethodType( f, nd, d );
mt.next = hashTable[hashBucket];
hashTable[hashBucket] = mt;
return mt;
}
/*
* static buffers used by parseSignature (and its parser) only
*/
static int detailsbuffer[] = new int[257];
static int formSyllables[] = new int[ CVMSignatureParser.NDATAWORDS ];
public static CVMMethodType
parseSignature( String sig ){
CVMSignatureParser p = new CVMSignatureParser( sig, detailsbuffer, formSyllables );
p.parse();
CVMSigForm f = CVMSigForm.lookup( p.nSyllables(), formSyllables );
return lookup( f, p.nDetails(), detailsbuffer );
}
}
class CVMSignatureParser extends util.SignatureIterator implements CVMTypeCode, util.ClassFileConst {
/* instance data */
int details[];
int formData[];
int detailNo = 0;
int sylNo = 0;
/* static data */
public static final int NDATAWORDS = 1+257/CVMSigForm.SYLLABLESPERDATUM;
/* constructor */
public
CVMSignatureParser( String sig, int detailArray[], int formDataArray[] ){
super( sig );
details = detailArray;
formData = formDataArray;
}
/* instance methods */
/* to return the number of details, form syllables */
public int nDetails(){ return detailNo; }
public int nSyllables(){ return sylNo; }
/* to run the whole show, in the right order */
public boolean parse(){
for ( int i = 0; i < NDATAWORDS; i++ ){
formData[i] = 0;
}
try {
iterate_returntype();
iterate_parameters();
insertSyllable( CVM_T_ENDFUNC );
} catch ( util.DataFormatException e ){
e.printStackTrace();
return false;
}
return true;
}
/* to manipulate the form syllables */
private void insertSyllable( int v ){
int wordno = sylNo / CVMSigForm.SYLLABLESPERDATUM;
int nshift = 4*( sylNo % CVMSigForm.SYLLABLESPERDATUM );
formData[wordno] |= v << nshift;
sylNo+=1;
}
/* called back from iterate_parameters and iterate_returntype */
public void do_void(){ insertSyllable( CVM_T_VOID ); }
public void do_int() { insertSyllable( CVM_T_INT ); }
public void do_boolean(){ insertSyllable( CVM_T_BOOLEAN ); }
public void do_char(){ insertSyllable( CVM_T_CHAR ); }
public void do_short(){ insertSyllable( CVM_T_SHORT ); }
public void do_long(){ insertSyllable( CVM_T_LONG ); }
public void do_double(){ insertSyllable( CVM_T_DOUBLE ); }
public void do_float(){ insertSyllable( CVM_T_FLOAT ); }
public void do_byte(){ insertSyllable( CVM_T_BYTE ); }
public void do_array( int depth, int tstart, int tend ){
int cookie = CVMDataType.parseSignature( sig.substring( tstart-depth, tend+1 ) );
insertSyllable( CVM_T_OBJ );
details[detailNo++] = cookie;
}
public void do_object( int tstart, int tend ){
do_array( 0, tstart, tend );
}
}