📄 javacodecompact.java
字号:
boolean success = new JavaCodeCompact().process( clist ); if ( !success ){ System.out.flush(); System.err.flush(); System.exit(1); } return; } /* * ALL THIS IS FOR ROMIZATION */ /* * Iterate through all known classes. * Iterate through all constant pools. * Look at ClassConstants. If they are unbound, * and if they are references to array classes, * then instantiate the classes and rebind. */ public boolean instantiateArrayClasses( ClassInfo classTable[], boolean verbose ){ int nclasses = classTable.length; boolean good = true; // For EVM, make sure that all arrays of basic types // are instantiated! String basicArray[] = { "[C", "[S", "[Z", "[I", "[J", "[F", "[D", "[B", "[Ljava/lang/Object;" // not strictly basic. }; for ( int ino = 0; ino < basicArray.length; ino++ ){ if ( ! collectArrayClass( basicArray[ino], verbose )){ good = false; } } // Now dredge through all class constant pools. for ( int cno = 0; cno < nclasses; cno++ ){ ClassInfo c = classTable[cno]; ConstantObject ctable[] = c.constants; if ( ctable == null ) continue; int n = ctable.length; for( int i = 0; i < n; i++ ){ if ( ctable[i] instanceof ClassConstant ){ ClassConstant cc = (ClassConstant)ctable[i]; String cname = cc.name.string; if (cname.charAt(0) != Const.SIGC_ARRAY ){ continue; // not interesting } if ( cc.isResolved() ){ continue; // not interesting } if ( ! collectArrayClass( cname, verbose )){ good = false; } cc.forget(); // forget the fact that we couldn't find it } } } return good; } private boolean collectArrayClass( String cname, boolean verbose ){ // cname is the name of an array class // make sure it doesn't exist ( it won't if it came from a // class constant ), and instantiate it. For EVM, do the same with // any sub-array types. boolean good = true; do { if ( ClassInfo.lookupClass( cname ) != null ){ continue; // this one exists. But subclasses may not, so keep going. } try { arrayClasses.addElement( new ArrayClassInfo( verbose, cname ) ); } catch ( DataFormatException e ){ e.printStackTrace(); good = false; break; // out of do...while } } while ( (cname = cname.substring(1) ).charAt(0) == Const.SIGC_ARRAY ); return good; } /* * For each array class we just made up, process it like * all normal classes would have been processed up to this point. */ public void processArrayClasses( boolean verbose, ConstantPool x ){ Enumeration arrays = arrayClasses.elements(); while( arrays.hasMoreElements() ){ ArrayClassInfo a = (ArrayClassInfo)arrays.nextElement(); if ( verbose ){ System.out.println(Localizer.getString("javacodecompact.processing_array_class", a.className)); } a.externalize(x); //a.countReferences(); //a.smashConstantPool(); } } /* * My first attempt at factoring out VM specific code * is to subclass ClassClass. Perhaps I should be subclassing * components.ClassInfo itself, I don't know. * Anyway, this is the EVM-specific class factory. This * should be dependent on a runtime switch, obviously. * >>FIXME<<. */ VMClassFactory classMaker = new EVMClassFactory(); public ClassClass[] finalizeClasses(){ ClassClass classes[] = ClassClass.getClassVector(classMaker); int n = classes.length; if ( quicken ){ CodeHacker ch = new CodeHacker( t, qlossless, true, verbosity >= 2 ); for ( int i = 0; i < n; i++ ){ if ( verbosity != 0 )System.out.println(Localizer.getString("javacodecompact.quickening_code_of_class", classes[i].ci.className)); if ( ! ch.quickenCode( classes[i].ci ) ) fail = true; } } // constant pool smashing has to be done after quickening, // else it doesn't make much difference! for ( int i = 0; i < n; i++ ){ ClassInfo c = classes[i].ci; if ( verbosity != 0 )System.out.println(Localizer.getString("javacodecompact.reducing_constant_pool_of_class", c.className)); c.countReferences( !ROMout ); c.smashConstantPool(); c.relocateReferences(); } for ( int i = 0; i < n ; i++ ) classes[i].ci.allocateFieldsFromFieldtable(); /* * EVM doesn't do inlining, yet. * This last-minute preparation step might be generalized * to something more useful. */ /* //for ( int i = 0; i < n; i++) // classes[i].getInlining(); */ return classes; } private boolean writeROMFile( String outName, ClassInfo classTable[], Vector attributes ){ boolean good = true; ConstantPool sharedConstant = null; // // did arg parsing. // now do work. // good = instantiateArrayClasses( classTable, verbosity>1 ); processArrayClasses( verbosity>1, t ); PrimitiveClassInfo.init( verbosity > 1, t); // is better to have this after instantiating Array classes, I think. ClassClass classes[] = finalizeClasses(); int totalclasses = classes.length; // at this point, the classes array INCLUDES all the array // classes. classTable doesn't include these! // Since array classes CANNOT participate in sharing // (because of magic offsets) they are excluded from the // sharing calculation below. And because they don't have // any code... if (doShared) { // create a shared constant pool sharedConstant = new ConstantPool(); for (int i = 0; i < classTable.length; i++) addConstant2SharedPool(classTable[i], sharedConstant); // sort the reference count sharedConstant.doSort(); // run via the shared constant pool once. if (ClassClass.isPartiallyResolved(sharedConstant.getConstants())) { sharedConstant = ClassClass.makeResolvable(sharedConstant); } } else { for (int i = 0; i < totalclasses; i++) classes[i].adjustSymbolicConstants(); } for (int i = 0; i < totalclasses; i++) classes[i].ci.relocateAndPackCode(); if ( ! good ) return false; CoreImageWriter w; { String writername = "runtime."+archName+"Writer"; Class writerClass = null; try { writerClass = Class.forName( writername ); } catch ( ClassNotFoundException ee ){ System.err.println(Localizer.getString("javacodecompact.not_supported", archName)); return false; } try { w = (CoreImageWriter)(writerClass.newInstance()); } catch ( Exception e ){ System.err.println(Localizer.getString("javacodecompact.could_not_instantiate", writername)); e.printStackTrace( ); return false; } } w.init(classDebug, nativeTypes, verbosity>0, maxSegmentSize); Enumeration attr = attributes.elements(); while ( attr.hasMoreElements() ){ String val = (String)attr.nextElement(); if ( ! w.setAttribute( val ) ){ System.err.println(Localizer.getString("javacodecompact.bad_attribute_value",val)); } } if ( w.open( outName ) != true ) { w.printError( System.out ); good = false; } else { good = w.writeClasses(t, sharedConstant); w.printSpaceStats( System.out ); w.close(); } return good; } /* * For writing header files. We just instantiate * a runtime.HeaderDump and let it do all the work for us. */ private void writeNativesHeaders( ClassnameFilterList groups, ClassInfo c[], int nclasses ){ Hashtable dumpers = new Hashtable(7); for ( int i = 0; i < nclasses; i++ ){ ClassInfo ci = c[i]; String classname = ci.className; String[] types = groups.getTypes( classname ); for ( int j = 0; j < types.length; ++j) { String type = types[j]; HeaderDump hd = type != null ? (HeaderDump)dumpers.get(type) : null; if (hd == null) { try { Class dumperClass = Class.forName("runtime." + type + "Header"); hd = (HeaderDump)dumperClass.newInstance(); dumpers.put(type, hd); } catch (Exception e) { continue; } } String classFilename = hd.filename( classname ); String destFilename = classFilename+".h"; String nativesHeaderDestDir = (String)headerDirs.get(type); File nativesDestFile = new File(nativesHeaderDestDir, destFilename); File nativesDumpFile; boolean didWorkForNatives; if ( nativesDestFile.exists() ){ nativesDumpFile = new File( nativesHeaderDestDir, classFilename+".TMP" ); } else { nativesDumpFile = nativesDestFile; } try { PrintStream o = new BufferedPrintStream( new FileOutputStream( nativesDumpFile ) ); didWorkForNatives = hd.dumpHeader( ci, o ); o.close(); } catch ( IOException e ){ e.printStackTrace(); continue; } if ( didWorkForNatives ){ if ( nativesDestFile != nativesDumpFile ){ // copy and delete FileCompare.conditionalCopy( nativesDumpFile, nativesDestFile ); nativesDumpFile.delete(); } } else { nativesDumpFile.delete(); } } } } /* * For writing a C stub file. We just instantiate * a runtime.CStubGenerator and let it do all the work for us. */ private void writeCStubs( ClassInfo c[], int nclasses ){ // (conditional file creation copied from above) File destFile = new File( stubDestName ); File dumpFile; if ( destFile.exists() ){ dumpFile = new File( stubDestName+".TMP" ); } else { dumpFile = destFile; } try { PrintStream o = new BufferedPrintStream( new FileOutputStream( dumpFile ) ); CStubGenerator cs = new CStubGenerator( stubTraceMode, o ); cs.writeStubs( c, nclasses, nativeTypes ); o.close(); } catch ( IOException e ){ e.printStackTrace(); return; } if ( destFile != dumpFile ){ // copy and delete FileCompare.conditionalCopy( dumpFile, destFile ); dumpFile.delete(); } } // This function update the reference count and put constantobject // to the shared constant pool. private void addConstant2SharedPool(ClassInfo cinfo, ConstantPool cp) { for (int j = 0; j < cinfo.constants.length; j++) { if (cinfo.constants[j] == null) continue; int count = cinfo.constants[j].references; if (count > 0) { cinfo.constants[j] = cp.appendElement(cinfo.constants[j]); } } // update interfaces array if (cinfo.interfaces != null) { for (int k = 0 ; k < cinfo.interfaces.length; k++) { cinfo.interfaces[k] = (ClassConstant) cp.appendElement(cinfo.interfaces[k]); } } // update exception table (catchType) for (int i = 0; i < cinfo.methods.length; i++) { if ( cinfo.methods[i].exceptionTable != null) { for (int j = 0; j < cinfo.methods[i].exceptionTable.length; j++) { ClassConstant cc = cinfo.methods[i].exceptionTable[j].catchType; if (cc != null) { cinfo.methods[i].exceptionTable[j].catchType = (ClassConstant) cp.appendElement(cc); } } } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -