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 + -
显示快捷键?