cvmwriter.java

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

JAVA
1,949
字号
	}	declare( "const "+fieldArrayFlavor+" "+thisTableName, classOut);	fieldTableName = "&"+thisTableName;	fieldTableSize = nfields;    }    void writeFields(CVMClass c) {	// Note: Should deal with > 255 fields.	// Today is not that day. Just do the simple case.	FieldInfo m[] = c.classInfo.fields;	if ( (m == null) || (m.length== 0)){	    fieldTableName = "0";	    fieldTableSize = 0;	    return;	}	int nfields = m.length;	declareFieldArray( c );	classOut.print( " = {\n");	for ( int i = 0; i < nfields; i++ ){	    int fbIndex = i % cbRepeat;	    FieldInfo f = m[i];	    int typeid = CVMDataType.parseSignature(getUTF(f.type));	    int nameid = CVMMemberNameEntry.lookupEnter(getUTF(f.name));	    String nameAndType = "RAW_TYPEID(0x" + Integer.toHexString(nameid) +                                 ", 0x" + Integer.toHexString(typeid) + ")";	    //System.out.println( nameAndType+" => "+Integer.toHexString(typeid) );	    int access = CVMDataAccessFlags(f.access);	    int offset = f.instanceOffset;	    /* field offsets are always mod cbRepeat and we have to emit a cb	     * entry before each block of cbRepeat fields. */	    if (fbIndex == 0) {		if (i != 0) {		    classOut.print( "\t},\n");		}		classOut.print( "\t&"+classBlockName+",\n\t{\n" );	    }	    // static members use simple byte offset	    // instance members include size of header info	    if (f.isStaticMember()) {		classOut.print("\tCVM_INIT_FIELDBLOCK(" + nameAndType +                               "," + access + "," + fbIndex +                               ", CVM_STATIC_OFFSET(" + offset + ")),\n");	    } else {		classOut.print("\tCVM_INIT_FIELDBLOCK(" + nameAndType +                               "," + access + "," + fbIndex +                               ", CVM_FIELD_OFFSET(" + offset + ")),\n");	    }	}	classOut.println("}};");	this.nfields += nfields;    }    private String methodBlockAddress( MethodInfo mi ){	CVMMethodInfo em = (CVMMethodInfo)(mi.vmMethodInfo);	CVMClass      ec = (CVMClass)(mi.parent.vmClass);	int n = mi.index;	/* 	 * 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. The ability	 * to determine whether a class has writable methods has been	 * added to CVMClass.  	 */        if (mutableMBs || ec.hasWritableMethods()) {            // had better not be an interface.            return "&CVMROMGlobals." + ec.getNativeName() + "_methods.mb" +                   (n/cbRepeat+1) + "[" + n%cbRepeat + "]";        }	// had better not be an interface.        return "&" + ec.getNativeName() + "_methods.mb" + (n/cbRepeat+1) +               "[" + n%cbRepeat + "]";     }    private static String fieldBlockAddress( FieldInfo f ){	// pretty disgusting.	// if this is frequent enough, find a better way!	ClassInfo c = f.parent;	FieldInfo cf[] = c.fields;	int n = f.index;	//for ( n = 0; cf[n] != f; n++ ) // TRY THIS.	 //   ;	// assume we found it.	String parentName = ((CVMClass)(c.vmClass)).getNativeName();	return "&"+parentName+"_fields.fb"+(n/cbRepeat+1)+"["+n%cbRepeat+"]";    }    private static final int unresolvedCVMConstantMap[] = {	CVM_CONSTANT_Invalid,	CVM_CONSTANT_Utf8,	CVM_CONSTANT_Invalid,	CVM_CONSTANT_Integer|CVM_CONSTANT_POOL_ENTRY_RESOLVED,	CVM_CONSTANT_Float|CVM_CONSTANT_POOL_ENTRY_RESOLVED,	CVM_CONSTANT_Long|CVM_CONSTANT_POOL_ENTRY_RESOLVED,	CVM_CONSTANT_Double|CVM_CONSTANT_POOL_ENTRY_RESOLVED,	CVM_CONSTANT_ClassTypeID,	CVM_CONSTANT_StringObj|CVM_CONSTANT_POOL_ENTRY_RESOLVED,	CVM_CONSTANT_Fieldref,	CVM_CONSTANT_Methodref,	CVM_CONSTANT_InterfaceMethodref,	CVM_CONSTANT_NameAndType    };    private static final int resolvedCVMConstantMap[] = {	CVM_CONSTANT_Invalid,	CVM_CONSTANT_Utf8,	CVM_CONSTANT_Invalid,	CVM_CONSTANT_Integer|CVM_CONSTANT_POOL_ENTRY_RESOLVED,	CVM_CONSTANT_Float|CVM_CONSTANT_POOL_ENTRY_RESOLVED,	CVM_CONSTANT_Long|CVM_CONSTANT_POOL_ENTRY_RESOLVED,	CVM_CONSTANT_Double|CVM_CONSTANT_POOL_ENTRY_RESOLVED,	CVM_CONSTANT_ClassBlock|CVM_CONSTANT_POOL_ENTRY_RESOLVED,	CVM_CONSTANT_StringObj|CVM_CONSTANT_POOL_ENTRY_RESOLVED,	CVM_CONSTANT_FieldBlock|CVM_CONSTANT_POOL_ENTRY_RESOLVED,	CVM_CONSTANT_MethodBlock|CVM_CONSTANT_POOL_ENTRY_RESOLVED,	CVM_CONSTANT_MethodBlock|CVM_CONSTANT_POOL_ENTRY_RESOLVED,	CVM_CONSTANT_NameAndType    };    private static int CVMconstantTag( ConstantObject c){	int t;	if ( c.isResolved() ){	    t = resolvedCVMConstantMap[ c.tag ];	    if (t == CVM_CONSTANT_NameAndType){		String sig = ((NameAndTypeConstant)c).type.string;		t = (sig.charAt(0) == SIGC_METHOD) ? 		    CVM_CONSTANT_MethodTypeID : CVM_CONSTANT_FieldTypeID;	    }	} else {	    t = unresolvedCVMConstantMap[ c.tag ];	    if (t == CVM_CONSTANT_NameAndType){		String sig = ((NameAndTypeConstant)c).type.string;		t = (sig.charAt(0) == SIGC_METHOD) ? 		    CVM_CONSTANT_MethodTypeID : CVM_CONSTANT_FieldTypeID;	    }	}	return t;    }    // return address of this type table.    private String writeTypeTable( ConstantObject constants[], String name ){	int clen = constants.length;	String ttname = name+"_tt";	auxOut.print("CVMUint8 "+ttname+"[] = { 0,");	int j = 99;	for ( int i = 1; i < clen; i+=constants[i].nSlots ){	    if ( j >= 10 ){		auxOut.print("\n    ");		j = 1;	    } else {		j += 1;	    }	    auxOut.print(CVMconstantTag(constants[i])+",");	    if (constants[i].nSlots == 2){		auxOut.print(" 0,"); // 2nd word of 2-word constant 		j += 1;	    }	}	auxOut.println("\n};");	headerOut.println("extern CVMUint8 "+ttname+"["+clen+"];");	return "&"+ttname;    }    // return address of this array Info.    private String writeArrayInfo( ArrayClassInfo info, String name ){	String arrayInfoName = name+"_ai";	classOut.println("STATIC const union {");	classOut.println("\tCVMArrayInfo ai;");	classOut.println("\tCVMConstantPool constantpool;");	classOut.println("} "+arrayInfoName+" = {{");	classOut.println("\t"+info.depth+", "+info.baseType+",");	classOut.println("\t(CVMClassBlock*)&"+		    cbName((CVMClass)info.baseClass.find().vmClass)+",");	classOut.println("\t(CVMClassBlock*)&"+		    cbName((CVMClass)info.subarrayClass.find().vmClass));	classOut.println("}};");	return "&"+arrayInfoName+".ai";    }     // return address of this constant pool.    private String writeConstants(ConstantPool cp, 				  String name,				  boolean export) {	ConstantObject constants[] = cp.getConstants();	int clen = constants.length;	if ( (clen == 0) || (clen == 1 ) ){	    return "0";	}	// Check if we need a type table.  When we write the class, we	// check for unquickened bytecodes.  If we find any, we mark	// the constant pool as needing a type table.  The check for	// unresolved entries should be redundant, because unreferenced	// entries should have been removed, and referenced entries	// should have an unquickened reference.	boolean doTypeTable = cp.needsTypeTable() ||	    ClassClass.isPartiallyResolved(cp);	if ( doTypeTable && !classLoading ){	    // in future, do something more useful here.	    System.err.println(Localizer.getString("cwriter.no_class_loading"));	    // write the type table out anyway, in case	    // there is someone to look at it at runtime!	}	String typeTableName;	if ( doTypeTable ){	    typeTableName = "CP_ADDR(" + writeTypeTable( constants, name ) + ")";	}else{	    typeTableName = "CP_ADDR(0)";	}	String constantPoolName = name+"_cp";	classOut.print( doTypeTable ? "" : "const ");	classOut.println("CVMAddr "+constantPoolName+"["+(clen)+"] = {");	classOut.println("	(CVMAddr)"+typeTableName+",");	if (export) {	    // Export in the global header for multiple components of	    // romjava files to find	    headerOut.print("extern ");	    headerOut.print( doTypeTable ? "" : "const ");	    headerOut.println("CVMAddr "+			      constantPoolName+"["+(clen)+"];");	}	for ( int i = 1; i < clen; i+=constants[i].nSlots ){	    classOut.print("    ");	    writeConstant( constants[i], classOut, "CP_" );	    classOut.println(",");	}	classOut.println("};");	nconstants += clen;	return constantPoolName;    }    private void declareClassblock( CVMClass c, int innerClassCount ){	String myName = c.getNativeName();	String classblockFlavor = "struct CVMClassBlock"+innerClassCount;        if (!classblockSizes.get(innerClassCount)) {	    // need to declare a classblock-like struct with innerClassCount	    // elements in its CVMInnerClassInfo array	    if ( innerClassCount < 1 ){		headerOut.println(classblockFlavor +                                  " { CVMClassBlock classclass; };");	    } else {                headerOut.println(classblockFlavor +                                  " { CVMClassBlock classclass; " +                                  "CVMUint32 innerClassesCount; " +                                  "CVMInnerClassInfo innerClasses[ " +                                  innerClassCount + "]; };");	    }            classblockSizes.set(innerClassCount);        }	declare( "const "+classblockFlavor+" "+myName+"_Classblock", classOut);    }    // helper for classBitMap    private static int GCbits( FieldInfo slottable[], int first, int last )    {	int mapval = 0;	for ( int i = first; i < last; i++ ){	    switch ( slottable[i].type.string.charAt(0) ){	    case 'L':	    case '[':		// this is a reference.		mapval |= 1<<(i-first);	    }	}	return mapval;    }    //    // compute the GC bit map for a class.    // if it is big, then write it out as well. In any case,    // return a string to use to initialize the gcMap field in the CVMClassBlock    //    private String classBitMap( CVMClass c ){	if ( c.isArrayClass() ){	    // either an array of primitive or an array of objects.	    ArrayClassInfo ac = (ArrayClassInfo)(c.classInfo);	    if ( (ac.depth==1) && (ac.baseType!=T_CLASS) )		return "0"; // contains no references	    else		return "1"; // contains nothing but references.	}	ClassInfo ci = c.classInfo;	FieldInfo ft[] = ci.slottable;	if ( (ft==null) || (ft.length==0) ) return "0";	int nslots;	if ( (nslots=ft.length) <= 30 ){	    // easy case. Small object. Map can be represented in a word.	    return "0x"+Integer.toHexString(GCbits(ft,0,nslots)<<2);	} else {	    // hard case.	    String myName = c.getNativeName()+"_gcBits";	    int    nWords = (nslots+31)/32;	    classOut.print( "STATIC const struct { " + 			    "CVMUint16 maplen; CVMUint32 map["+nWords+"]; } ");	    classOut.print( myName );	    classOut.print( " = { ");	    classOut.print( nWords );	    classOut.print( ",\n    {" );	    for ( int i = 0; i < nslots; i+= 32 ){		classOut.print("0x"+Integer.toHexString(GCbits(ft, i,						    Math.min( i+32, nslots))));		classOut.print(", ");	    }	    classOut.println("} };");	    return "(CVMAddr)(((char*)&"+myName+")+ CVM_GCMAP_LONGGCMAP_FLAG)";	}    }    private void writeClassinfo( int classno, CVMClass c,				 int clinitIdx, int nStaticWords ){	if (c.hasStaticInitializer) {	    nClinits++;	}	String superName    = (c.classInfo.superClassInfo == null)			    ? ("0")			    : ("&" + cbName((CVMClass)                                         c.classInfo.superClassInfo.vmClass));	String myStaticName = (c.nStaticWords == 0) 			    ? ("0")			    : ("(CVMJavaVal32*)STATIC_STORE_ADDRESS(0)");	int innerClassCount = (c.classInfo.innerClassAttr == null)			    ? (0)			    : (c.classInfo.innerClassAttr.getInnerClassCount());	String runtimeFlags = (c.hasStaticInitializer)			    ? ("CVM_ROMCLASS_WCI_INIT")			    : ("CVM_ROMCLASS_INIT");	MethodInfo vtbl[]   = c.classInfo.methodtable;	String methodTableName;	int methodTableCount;	String gcBits;	/*	 * Note: If this is a primitive class, the	 * typecode is stored in the methodTableCount field.	 * Since these things cannot be instantiated, they need	 * no virtual methods.	 */	if ( c.isPrimitiveClass() ){	    methodTableCount = c.typecode();	    methodTableName = "0";	} else {	    // vtbl == null may occur for array classes! 	    methodTableCount = (vtbl==null)?0:vtbl.length;	    if (methodTableCount > 0) {		methodTableName = c.getNativeName()+"_mt";	    } else if (c.isArrayClass()) {                methodTableCount =                    c.classInfo.superClassInfo.methodtable.length;		methodTableName = "java_lang_Object_mt";	    } else { /* must be an interface */		methodTableName = "0";	    }	}	// classBitMap may do output, so it needs	// to be called before declareClassblock!	gcBits = classBitMap( c );	declareClassblock( c, innerClassCount );	int classid = c.getClassId();	//System.out.println( c.ci.className+" => "+Integer.toHexString(classid) );	classOut.println(" = {\n    CVM_INIT_CLASSBLOCK( "+gcBits+", " +                         "RAW_TYPEID(0, 0x" + Integer.toHexString(classid) +                         "), \"" + c.classInfo.className + "\",");	classOut.println("    "+superName+",");	classOut.println("    "+constantPoolName+", ");	classOut.println("    "+interfaceTableName+",");	classOut.println("    "+methodArrayName+",");	classOut.println("    "+fieldTableName+", "+myStaticName+",");	classOut.println("    "+constantPoolSize+", "+methodTableSize+", "+		    fieldTableSize+", "+methodTableCount+", "+		    c.CVMflags()+", "+runtimeFlags+", "+		    nStaticWords+" + "+clinitIdx+		    ", OBJ_SIZE("+c.instanceSize()+"), ");	classOut.println("    (CVMClassICell*)(&CVM_classICell["+classno+"]), ");	/* The slots for clinitEE is appended to 'staticStoreName'. */	/* 	 * Moved global variables to CVMROMGlobals	 */	classOut.println("    (CVMExecEnv**)&CVMROMGlobals."+staticStoreName+					"["+nStaticWords+" + "+clinitIdx+"],");	classOut.println("    "+checkedExceptionName+", ");	if (classDebug && c.classInfo.sourceFileAttr != null) {

⌨️ 快捷键说明

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