cvmwriter.java
来自「This is a resource based on j2me embedde」· Java 代码 · 共 1,949 行 · 第 1/5 页
JAVA
1,949 行
boolean isAbstract= (access&CVM_METHOD_ACC_ABSTRACT) != 0; // // Item #2 // String invoker = isAbstract ? "CVM_INVOKE_ABSTRACT_METHOD" : isNative ? ( isClassCNI(c.classInfo.className) ? "CVM_INVOKE_CNI_METHOD" : ( synchro ? "CVM_INVOKE_JNI_SYNC_METHOD" : "CVM_INVOKE_JNI_METHOD" )) : ( synchro ? "CVM_INVOKE_JAVA_SYNC_METHOD" : "CVM_INVOKE_JAVA_METHOD" ); // // note the offset in the exception array, // and add to that array as necessary. // int exceptions; if ((meth.method.exceptionsThrown != null) && (meth.method.exceptionsThrown.length != 0)) { ClassConstant thrown[] = meth.method.exceptionsThrown; int net = thrown.length; exceptions = currCheckedException; checkedExceptionVector[currCheckedException++] = net; for ( int j = 0; j < net; j++ ){ checkedExceptionVector[currCheckedException++] = thrown[j].index; } } else { // Note we have changed this from ((unsigned short) // -1) to 0 to be consistent with the documentation in // classes.h. A checkedExceptionsOffset of 0 indicates // no checked exceptions for the method. Also see the // allocation of the checkedExceptionVector above. exceptions = 0; } // // Item #3 // int argssize = meth.method.argsSize; int tableIndex = meth.methodOffset(); // // Remember these items // We won't know whether a class is compressible // until after all the triples for all methods have been seen // methStats.record(argssize, invoker, access); // // Also see whether the method table index and // checkedExceptionsOffset are encodable in one byte each. // if (tableIndex >= 256) { c.setCompressible(false); } if (exceptions >= 256) { c.setCompressible(false); } } } void writeMethods(CVMClass c) { boolean isCompressible = c.isCompressible(); String cbname_comma = "&" + cbName(c) + ","; CVMMethodInfo m[] = c.methods; int nCheckedExceptions = 0; int currCheckedException = 0; int checkedExceptionVector[]; boolean writableMethods = mutableMBs; if ( (m == null) || (m.length == 0 )){ methodArrayName = "0"; checkedExceptionName = "0"; methodTableSize = 0; return; } int nmethod = m.length; String thisTableName = c.getNativeName()+"_methods"; String thisExceptionName = null; 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 ( mi.code != null ){ writeCode( meth ); } if ( meth.codeHasJsr() ){ writableMethods = true; } } // // if any methods declare that they throw any exceptions, // we need to construct the exception vector. if ( nCheckedExceptions == 0 ){ checkedExceptionName = "0"; checkedExceptionVector = null; } else { thisExceptionName = c.getNativeName()+"_throws"; checkedExceptionName = thisExceptionName; // Ensure that item 0 in this array is always unused. // See classes.h. nCheckedExceptions++; checkedExceptionVector = new int[ nCheckedExceptions ]; checkedExceptionVector[0] = 0; currCheckedException = 1; } boolean emittedNativeHeader = false; // // Look to see whether we can compact this // for ( int i = 0; i < nmethod; i++ ){ CVMMethodInfo meth = m[i]; int access = meth.CVMflags(); if (!emittedNativeHeader && ((access&CVM_METHOD_ACC_NATIVE)!=0)) { String subdir; subdir = isClassCNI(c.classInfo.className) ? "cni/" : "jni/"; headerOut.println("#include \"generated/" + subdir + Util.convertToClassName(c.classInfo.className)+".h\""); emittedNativeHeader = true; } boolean synchro = (access&CVM_METHOD_ACC_SYNCHRONIZED)!=0; boolean isNative = (access&CVM_METHOD_ACC_NATIVE)!=0; boolean isAbstract= (access&CVM_METHOD_ACC_ABSTRACT) != 0; String invoker = isAbstract ? "CVM_INVOKE_ABSTRACT_METHOD" : isNative ? ( isClassCNI(c.classInfo.className) ? "CVM_INVOKE_CNI_METHOD" : ( synchro ? "CVM_INVOKE_JNI_SYNC_METHOD" : "CVM_INVOKE_JNI_METHOD" )) : ( synchro ? "CVM_INVOKE_JAVA_SYNC_METHOD" : "CVM_INVOKE_JAVA_METHOD" ); int argssize = meth.method.argsSize; CVMMethodStats.Entry entry = methStats.lookup(argssize, invoker, access); // // Cannot encode in one byte, therefore cannot compress // if (entry.getIdx() >= 256) { c.setCompressible(false); } meth.statsEntry = entry; } // // Update the compressibility of class c // isCompressible = isCompressible && c.isCompressible(); // // isCompressible cannot be true if the mb's are to be read-only // isCompressible = isCompressible && writableMethods; // if any method has a JSR, then its method block, and thus // all of them, must be writable, so we can replace its code, bundled // with its JavaMethodDescriptor. declareMethodArray( c, writableMethods, isCompressible ); String cbDeclaration; if (isCompressible) { cbDeclaration = "CVM_INIT_METHODARRAY_CB_WITH_COMPRESSED_MBS"; } else { cbDeclaration = "CVM_INIT_METHODARRAY_CB_WITH_UNCOMPRESSED_MBS"; } classOut.print(" = {\n\t" + cbDeclaration + "(&" + classBlockName + "),\n\t{\n"); for ( int i = 0; i < nmethod; i++ ){ CVMMethodInfo meth = m[i]; if (meth.method.hasCheckinits) { nMethodsWithCheckinitInvokes++; } int mbIndex = i % cbRepeat; int typeid = meth.sigType.entryNo; int nameid = CVMMemberNameEntry.lookupEnter( getUTF(meth.method.name)); String nameAndType = "RAW_TYPEID(0x" + Integer.toHexString(nameid) + ", 0x" + Integer.toHexString(typeid) + ")"; int access = meth.CVMflags(); boolean synchro = (access&CVM_METHOD_ACC_SYNCHRONIZED)!=0; boolean isNative = (access&CVM_METHOD_ACC_NATIVE)!=0; boolean isAbstract= (access&CVM_METHOD_ACC_ABSTRACT) != 0; String invoker = meth.statsEntry.getInvoker(); /* By default let interpreter do invocation in all except native methods. Compilation might change invoker function */ String jitInvoker = isNative ? ( isClassCNI(c.classInfo.className) ? "CVMCCMinvokeCNIMethod" : "CVMCCMinvokeJNIMethod" ) : "CVMCCMletInterpreterDoInvoke"; // // note the offset in the exception array, // and add to that array as necessary. int exceptions; if ((meth.method.exceptionsThrown != null) && (meth.method.exceptionsThrown.length != 0)) { ClassConstant thrown[] = meth.method.exceptionsThrown; int net = thrown.length; exceptions = currCheckedException; checkedExceptionVector[currCheckedException++] = net; for ( int j = 0; j < net; j++ ){ checkedExceptionVector[currCheckedException++] = thrown[j].index; } } else { // Note we have changed this from ((unsigned short) // -1) to 0 to be consistent with the documentation in // classes.h. A checkedExceptionsOffset of 0 indicates // no checked exceptions for the method. Also see the // allocation of the checkedExceptionVector above. exceptions = 0; } int argssize = meth.method.argsSize; int tableIndex = meth.methodOffset(); /* * method offsets are always mod 'cbRepeat' and we have to * emit a cb entry before each block of 'cbRepeat' * methods. */ if ((mbIndex == 0) && (i != 0) && !isCompressible && !writableMethods) { // Output the repeated cb only if we are emitting read-only // method blocks. classOut.print( "\t},\n"); classOut.print( "\t&"+classBlockName+",\n\t{\n" ); } if (isCompressible) { // The C compiler checks that the values here are // really compressed within the proper sizes. We get // warnings if we exceed the maximum width for a given // data field. // // entryIdx encapsulates argssize, invoker, and access flags int entryIdx = meth.statsEntry.getIdx(); classOut.print("\tCVM_INIT_METHODBLOCK_IMMUTABLE_COMPRESSED(" + cbname_comma + nameAndType + "," + tableIndex + "," + entryIdx + "," + mbIndex + "," + exceptions + ","); } else if (writableMethods) { classOut.print("\tCVM_INIT_METHODBLOCK_IMMUTABLE(" + cbname_comma + nameAndType + "," + tableIndex + "," + argssize + "," + invoker + "," + access + "," + mbIndex + "," + exceptions + ","); } else { classOut.print("\tCVM_INIT_METHODBLOCK(" + cbname_comma + jitInvoker + "," + nameAndType + "," + tableIndex + "," + argssize + "," + invoker + "," + access + "," + mbIndex + "," + exceptions + ","); } if ( isAbstract ){ classOut.print("(CVMJavaMethodDescriptor*)"+i+"),\n"); } else if ( isNative ){ if (isClassCNI(c.classInfo.className)) { String jniName = meth.method.getNativeName(true); String eniName = "CNI" + jniName.substring(5); classOut.print("(CVMJavaMethodDescriptor*)&" + eniName + "),\n"); } else { classOut.print("(CVMJavaMethodDescriptor*)&" + meth.method.getNativeName(true)+"),\n"); } } else { classOut.print("&(" + meth.getNativeName() + ".u.jmd)),\n"); } } classOut.print("}};\n"); this.nmethods += nmethod; if (writableMethods) { nClassesWithWritableMethodBlocks += 1; nWritableMethodBlocks += nmethod; } // // now, if there are any exception-catch clauses // that need to be represented, print out the table. if (nCheckedExceptions != 0) { classOut.println("STATIC const CVMUint16 " + thisExceptionName + "[] = {"); int j = 0; for (int i = 0; i < nCheckedExceptions; i++) { if (j >= 8) { classOut.print("\n "); j = 0; } else { j += 1; } classOut.print( checkedExceptionVector[i]+", "); } classOut.println("\n};"); } } /* * Write out the InnerClassInfo structure. This structure will contain * information about all referenced inner classes. */ private void writeInnerClasses(CVMClass c) { //Write information about each inner class contained in this class. int innerClassCount = c.classInfo.innerClassAttr.getInnerClassCount(); InnerClassAttribute ica = c.classInfo.innerClassAttr; classOut.println(" " + innerClassCount + ", {"); for (int j=0; j < innerClassCount; j++) { // write out the indexes and access flags of this inner class. classOut.print(" {"); classOut.print(ica.getInnerInfoIndex(j)); classOut.write(','); classOut.print(ica.getOuterInfoIndex(j)); classOut.write(','); /* innerNameIndex not supported because utf8 cp entries * are not kept around. classOut.print(ica.getInnerNameIndex(j)); */ classOut.print('0'); classOut.write(','); classOut.print(ica.getAccessFlags(j)); classOut.print("},\n"); } classOut.println(" }"); ninnerclasses += innerClassCount; } void mungeAllIDsAndWriteExternals(ClassClass classes[]) { } private static int CVMDataAccessFlags( int access ){ int a = 0; if ( (access&ACC_PUBLIC) != 0 ) a |= CVM_FIELD_ACC_PUBLIC; if ( (access&ACC_PRIVATE) != 0 ) a |= CVM_FIELD_ACC_PRIVATE; if ( (access&ACC_PROTECTED) != 0 ) a |= CVM_FIELD_ACC_PROTECTED; if ( (access&ACC_STATIC) != 0 ) a |= CVM_FIELD_ACC_STATIC; if ( (access&ACC_FINAL) != 0 ) a |= CVM_FIELD_ACC_FINAL; if ( (access&ACC_VOLATILE) != 0 ) a |= CVM_FIELD_ACC_VOLATILE; if ( (access&ACC_TRANSIENT) != 0 ) a |= CVM_FIELD_ACC_TRANSIENT; return a; } private void declareFieldArray( CVMClass c ){ // Note: Should deal with > 255 fields. // Today is not that day. Just do the simple case. FieldInfo m[] = c.classInfo.fields; int nfields = m.length; String thisTableName = c.getNativeName()+"_fields"; String fieldArrayFlavor = "struct CVMFieldArray"+nfields; if ( !fieldArraySizes.get( nfields ) ){ // need to declare a structure containing a classblock pointer // plus "nfields" CVMFieldBlock structures int i; headerOut.print(fieldArrayFlavor+" {"); if (nfields > cbRepeat) headerOut.println(); int numFieldArrays = (nfields-1) / cbRepeat + 1; for (i = 1; i <= numFieldArrays; i++) { int nfields2; // # fields in this field array if (i == numFieldArrays) { nfields2 = (nfields-1) % cbRepeat + 1; } else { nfields2 = cbRepeat; } headerOut.print(" CVMClassBlock const *cb" + i + ";" + " CVMFieldBlock fb" + i + "[" + nfields2 + "];"); if (nfields > cbRepeat) { headerOut.println(); } } headerOut.println(" };"); fieldArraySizes.set( nfields );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?