cvmwriter.java

来自「This is a resource based on j2me embedde」· Java 代码 · 共 1,949 行 · 第 1/5 页

JAVA
1,949
字号
    }    public void printError( java.io.PrintStream o ){	if ( failureMode != null ){	    failureMode.printStackTrace( o );	}     }    protected void declare( String declaration,  BufferedPrintStream curOut ){	headerOut.print( "extern " );	headerOut.print( declaration );	headerOut.write(';');	headerOut.write('\n');	curOut.print( declaration );    }    public static String getUTF( UnicodeConstant u ){	return u.toUTF();    }    /*     * For Java methods,     * write out the structure which will be initialized with a     * JavaMethodDescriptor and its associated structures: code array,     * line numbers, exceptions, local variables     */    private void writeCode(CVMMethodInfo meth) {	MethodInfo 		  mi 	  = meth.method;	LineNumberTableEntry[]	  lntab	  = mi.getLineNumberTable();	LocalVariableTableEntry[] locvartab = mi.getLocalVariableTable();	int	codeLengthRoundup = (mi.code.length+3)&~3;	int 	nTryCatch 	  = (mi.exceptionTable==null) ? 0 	       				  : mi.exceptionTable.length;	int	nLineNumbers = (classDebug && lntab != null) ? lntab.length : 0;	int	nLocals = (classDebug && locvartab != null) ? locvartab.length : 0;	String	codeBlockName	  = meth.getNativeName();	String	descriptorTypeTag = codeBlockName+"MDType";	CCodeWriter declareOut;	boolean impureCode = noPureCode || !meth.isCodePure();	classOut.println("\n/* Code block for "+meth.method.qualifiedName()+" */");	/*	 * Declare the structure which will be initialized with a	 * JavaMethodDescriptor and its associated structures: code array,	 * line numbers, exceptions, local variables	 * Unlike several of the other structures, we do not bother remembering	 * and reusing prior definitions -- there are so many dimensions it doesn't	 * see worthwhile.	 * In fact, the only reason this is not an anonimous structure is the	 * case where it has to be writable and initialized, for JVMTI.	 */	if ( ! impureCode ){	    // this might as well be static since there will be	    // no external references to it	    classOut.print("STATIC ");	    declareOut = classOut;	} else {	    headerOut.print("extern ");	    declareOut = headerOut;	}	declareOut.print("const struct ");	declareOut.print( descriptorTypeTag );	declareOut.println(" {\n    union {");	declareOut.println("        CVMJavaMethodDescriptor jmd;");	declareOut.println("        CVMUint" +		    ((meth.alignment() == 1) ? "8" : "32") +		    " align;\n    } u;");	declareOut.println("    CVMUint8 data["+codeLengthRoundup+"];");	if ( nTryCatch != 0 ){	    declareOut.println("    CVMExceptionHandler exceptionTable["+			nTryCatch+"];");	}	if ( nLineNumbers != 0 ){	    declareOut.println("    CVMLineNumberEntry lineNumberTable["+			nLineNumbers+"];");	}	if ( nLocals != 0 ){	    declareOut.println("    CVMLocalVariableEntry localVariableTable["+			nLocals+"];");	}	declareOut.print("} ");	/*	 * Now we have the shape of the data we need to supply the data itself	 * (themselves?)	 *	 * EITHER the MD has to be writable. in thise case the declaration above	 * was to the header file. Append to it the names of the master and	 * the working copy, emit the master, reserve space for the copy,	 * and don't forget the initialization instructions.	 *	 * OR the MD is read-only, const, so this is the thing itself	 */	if ( impureCode ){	    declareOut.print( codeBlockName );	    declareOut.print("Master;\n");	    declareOut.print(" extern struct " + descriptorTypeTag );	    declareOut.write(' ');	    declareOut.println( codeBlockName );	    declareOut.println(";");	    classOut.print("struct " + descriptorTypeTag );	    classOut.write(' ');	    classOut.println( codeBlockName );	    classOut.println(";");	    classOut.print( "const struct " );	    classOut.print( descriptorTypeTag );	    classOut.write(' ');	    classOut.print( codeBlockName );	    classOut.print( "Master" );            initInfo.addInfo("&" + codeBlockName + "Master",                             "&" + codeBlockName,                             "sizeof( struct " + descriptorTypeTag + ")");	} else {            classOut.print(codeBlockName);	}        classOut.print(" = {\n    { CVM_INIT_JAVA_METHOD_DESCRIPTOR(");	/*	 * Make sure locals are big enough for any return value.	 */	classOut.print(mi.stack+", "+Math.max(2,mi.locals));	classOut.print( ", ");	if ( meth.codeHasJsr() ){	    classOut.print("CVM_JMD_MAY_NEED_REWRITE|");	    if (meth.alignment() != 1) {		classOut.print("CVM_JMD_NEEDS_ALIGNMENT|");	    }	}	if (meth.isStrictFP()) {	    classOut.print("CVM_JMD_STRICT|");	}	classOut.print("0, " );	classOut.print(nTryCatch+", "+mi.code.length);	classOut.print(", "+nLineNumbers+", "+nLocals);	classOut.print(") },\n    {");	// output the code array	int j = 99;	byte[] methodCode = mi.code;	int l = methodCode.length;	for ( int i = 0; i <l; i++ ){	    if ( j >= 12 ){		classOut.print("\n\t");		j = 1;	    } else {		j+= 1;	    }	    classOut.printHexInt( methodCode[i]& 0xff );	    classOut.print(",");	}	classOut.print("\n    }");	ncodebytes += mi.code.length;	// output the CVMExceptionHandler[] (catch frames)	if ( nTryCatch != 0 ){	    classOut.println(",\n    {");	    for ( int i = 0; i < nTryCatch; i++ ){		ExceptionEntry e = mi.exceptionTable[i];                classOut.println("\t{ " + e.startPC + ", " + e.endPC + ", " +                                 e.handlerPC + ", " +                                 (e.catchType == null ? 0 : e.catchType.index) +                                 "},");	    }	    classOut.print("    }");	    ncatchframes += nTryCatch;	}	// output the CVMLineNumberEntry[]	if ( nLineNumbers != 0 ){	    classOut.println(",\n    {");	    for ( int i = 0; i < nLineNumbers; i++ ){		LineNumberTableEntry e = lntab[i];		classOut.println("\t{ "+e.startPC+", "+e.lineNumber+"},");	    }	    classOut.print("    }");	}	// output the CVMLocalVariableEntry[]	if ( nLocals != 0 ){	    classOut.println(",\n    {");	    for ( int i = 0; i < nLocals; i++ ){		LocalVariableTableEntry e = locvartab[i];		int typeid = CVMDataType.parseSignature(getUTF(e.sig));		int nameid = CVMMemberNameEntry.lookupEnter(getUTF(e.name));		classOut.println("\t{ "+e.pc0+", "+e.length+", "+e.slot+                    ", RAW_TYPEID_NAME_PART(0x" + Integer.toHexString(nameid) +                    "), RAW_TYPEID_TYPE_PART(0x" + Integer.toHexString(typeid) +                    ")},");	    }	    classOut.print("    }");	}	classOut.println("\n};");    }    //    // The cb repeats every 'cbRepeat' entries in MethodArray's and    // FieldArray's    //    static final int cbRepeat = 256;        private void handleMethodArrayDecl(String flavorName,				       int nmethods) {	// need to declare a structure containing a classblock pointer	// plus "nmethods" CVMMethodBlock structures	int i;	headerOut.print(flavorName+" {");	if (nmethods > cbRepeat)	    headerOut.println();	int numMethodArrays = (nmethods-1) / cbRepeat + 1;	for (i = 1; i <= numMethodArrays; i++) {	    int nmethods2; // # methods in this method array	    if (i == numMethodArrays) {		nmethods2 = (nmethods-1) % cbRepeat + 1;	    } else {		nmethods2 = cbRepeat;	    }	    headerOut.println(" CVMClassBlock const *cb" + i + ";" +			      " CVMMethodBlock mb" + i + 			      "[" + nmethods2 + "];");	    if (nmethods > cbRepeat) {		headerOut.println();	    }	}	headerOut.println(" };");    }    private void declareMethodArray( CVMClass c,				     boolean writeable,				     boolean compressible ){	String thisTableName = c.getNativeName()+"_methods";	String tableAddress = "&"+thisTableName;	int nmethods = c.methods.length;	String methodArrayFlavor = "struct CVMMethodArray"+nmethods;	String methodArrayImmutFlavor = "struct CVMMethodArrayImmut"+nmethods;	String methodArrayImmutCompFlavor =            "struct CVMMethodArrayImmutCompressed"+nmethods;	String immutFlavor;	String immutableType;	java.util.BitSet methArrSizes;        /* count the total number of romized methods */        nTotalMethods += nmethods;		if (compressible) {	    immutableType = "CVMMethodBlockImmutableCompressed";	    immutFlavor   = methodArrayImmutCompFlavor;	    methArrSizes  = compressibleMethodArraySizes;	} else {	    immutableType = "CVMMethodBlockImmutable";	    immutFlavor   = methodArrayImmutFlavor;	    methArrSizes  = methodArraySizes;	}	/*	 * Declare the runtime typedef	 */	if ( !runtimeMethodArraySizes.get(nmethods) ) {	    handleMethodArrayDecl(methodArrayFlavor, nmethods);	    runtimeMethodArraySizes.set(nmethods);	}	/*	 * And now, declare the proper immutable type	 */	if ( !methArrSizes.get( nmethods ) ) {	    /* The immutable version is easy. Just bundle all the immutable	       parts together, and let the initializer take care	       of the methods arrays */	    headerOut.print(immutFlavor+" {");	    headerOut.println(" CVMClassBlock const *cb; " + immutableType + 			      " mb["+ nmethods + "];");	    headerOut.println(" };");	    methArrSizes.set( nmethods );        }		if (writeable ){	    /*	     * Declare actual array, record copying information.	     * What we're about to initialize is the read-only master.	     */	    String masterName = thisTableName+"Master";	    /* 	     * Moved global variables to CVMROMGlobals.	     */	    /*	    declare(methodArrayFlavor+" "+thisTableName, classOut); 	    classOut.println(";");	    */            globalHeaderOut.println("    " + methodArrayFlavor + " " +                                    thisTableName + ";");	    initInfoForMBs.addInfo( "&"+masterName );	    declare( "const "+immutFlavor+" "+masterName, classOut );	} else {	    declare( "const "+methodArrayFlavor+" "+thisTableName, classOut);	}	/* 	 * Moved globals to CVMROMGlobals.  For classes without	 * writeable methods, there is (still) a constant global	 * variable <class>_methods - nothing has changed.  For	 * classes with writeable methods, the <class>_methods	 * variable lives in the CVMROMGlobals structure.  	 */	if (writeable) {	    methodArrayName = "&CVMROMGlobals." + thisTableName;	}	else {	    methodArrayName = tableAddress;	}	methodTableSize = nmethods;    }    //    // Find out variations of several method components to see whether    // compression opportunities exist.    //    // 1) Look for (argsSize, invokerIdx, accessFlags) triples. These    // don't vary much, so we can encode commonly occurring    // variants within 8-bits.    //    // 2) Check whether the method table index and checkedExceptionsOffset    // can each be encoded in a byte.    //    // If #1 and #2 hold, we can shave off a word from the immutable method    // block encoding.    //    void analyzeMethodsForCompression(CVMClass c) {	CVMMethodInfo m[] = c.methods;	int nCheckedExceptions = 0;	int currCheckedException = 0;	int checkedExceptionVector[];	if ( (m == null) || (m.length == 0 )){	    /* Nothing to do */	    return;	}	int nmethod =  m.length;	//	// Traverse all methods, and look for opportunities. If any	// one method in the methods of a class is not compressible,	// the entire method array is expanded in the "long" form	//	for ( int i = 0; i < nmethod; i++ ){	    CVMMethodInfo meth = m[i];	    MethodInfo    mi   = meth.method;	    if ( mi.exceptionsThrown != null ){		int n = mi.exceptionsThrown.length;		if ( n != 0 )		    nCheckedExceptions += n+1; // "1" is for the count word.	    }	}	//	// if any methods declare that they throw any exceptions,	// we need to construct the exception vector.	if ( nCheckedExceptions == 0 ){	    checkedExceptionVector = null;	} else {	    // Ensure that item 0 in this array is always unused.	    // See classes.h.	    nCheckedExceptions++;	    checkedExceptionVector = new int[ nCheckedExceptions ];	    checkedExceptionVector[0] = 0;	    currCheckedException = 1;	}	for ( int i = 0; i < nmethod; i++ ){	    CVMMethodInfo meth = m[i];	    //	    // Item #1	    //	    int access = meth.CVMflags();	    boolean synchro = (access&CVM_METHOD_ACC_SYNCHRONIZED)!=0;	    boolean isNative  = (access&CVM_METHOD_ACC_NATIVE)!=0;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?