Source Code Cross Referenced for CVMWriter.java in  » 6.0-JDK-Modules » j2me » runtime » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » j2me » runtime 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * @(#)CVMWriter.java	1.153	06/10/27
0003:         *
0004:         * Copyright  1990-2006 Sun Microsystems, Inc. All Rights Reserved.  
0005:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER  
0006:         *   
0007:         * This program is free software; you can redistribute it and/or  
0008:         * modify it under the terms of the GNU General Public License version  
0009:         * 2 only, as published by the Free Software Foundation.   
0010:         *   
0011:         * This program is distributed in the hope that it will be useful, but  
0012:         * WITHOUT ANY WARRANTY; without even the implied warranty of  
0013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  
0014:         * General Public License version 2 for more details (a copy is  
0015:         * included at /legal/license.txt).   
0016:         *   
0017:         * You should have received a copy of the GNU General Public License  
0018:         * version 2 along with this work; if not, write to the Free Software  
0019:         * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  
0020:         * 02110-1301 USA   
0021:         *   
0022:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa  
0023:         * Clara, CA 95054 or visit www.sun.com if you need additional  
0024:         * information or have any questions. 
0025:         *
0026:         */
0027:        package runtime;
0028:
0029:        import consts.Const;
0030:        import consts.CVMConst;
0031:        import components.*;
0032:        import vm.*;
0033:        import jcc.Util;
0034:        import util.*;
0035:        import java.util.Arrays;
0036:        import java.util.Comparator;
0037:        import java.util.Vector;
0038:        import java.util.Enumeration;
0039:        import java.util.Hashtable;
0040:        import java.io.OutputStream;
0041:
0042:        /*
0043:         * The CoreImageWriter for the Embedded VM
0044:         */
0045:
0046:        public class CVMWriter implements  CoreImageWriter, Const, CVMConst {
0047:
0048:            /* INSTANCE DATA */
0049:            protected Exception failureMode = null; // only interesting on falure
0050:
0051:            protected String outputFileName;
0052:            protected CCodeWriter classOut;
0053:            protected CCodeWriter auxOut;
0054:            protected OutputStream xxx;
0055:            protected OutputStream zzz;
0056:
0057:            protected String headerFileName = null;
0058:            protected CCodeWriter headerOut;
0059:            protected OutputStream yyy;
0060:
0061:            protected String globalHeaderFileName = null;
0062:            protected CCodeWriter globalHeaderOut;
0063:            protected OutputStream www;
0064:            /*
0065:             * The following only used if we're segmenting the output,
0066:             * which happens if this.init gets a maxSegSize > 0 
0067:             */
0068:            protected boolean segmentedOutput;
0069:            protected int maxClasses;
0070:            protected int curClasses = 0;
0071:            protected int nClassfileOut;
0072:            protected BufferedPrintStream listOut;
0073:
0074:            protected CVMStringTable stringTable;
0075:            protected CVMClass classes[];
0076:
0077:            private VMClassFactory classMaker = new CVMClassFactory();
0078:
0079:            private CVMInitInfo initInfo;
0080:            private CVMInitInfo initInfoForMBs;
0081:
0082:            boolean formatError = false;
0083:            boolean verbose = false;
0084:            boolean classDebug = false;
0085:            boolean lossless = false;
0086:            boolean mutableMBs = false;
0087:
0088:            private static final String staticInitThreadStoreName = "StaticInitThreadStorage";
0089:            private static final String stringArrayName = "CVM_ROMStrings";
0090:            private static final String masterStringArrayName = "CVM_ROMStringsMaster";
0091:            private static final String staticStoreName = "CVM_staticData";
0092:            private static final String numStaticStoreName = "CVM_nStaticData";
0093:            private static final String masterStaticStoreName = "CVM_StaticDataMaster";
0094:
0095:            private ClassnameFilterList nativeTypes;
0096:            private ClassnameFilter invisibleClassList = new ClassnameFilter();
0097:
0098:            private boolean classLoading = true; // by default.
0099:
0100:            // Place all byte codes into read-write memory.  Useful for setting
0101:            // breakpoints.
0102:            protected boolean noPureCode = false;
0103:
0104:            private boolean doShared;
0105:            private String sharedConstantPoolName;
0106:            private int sharedConstantPoolSize;
0107:
0108:            private CVMMethodType[] methodTypes;
0109:            private int[] nMethodTypes;
0110:            private int totalMethodTypes;
0111:
0112:            //
0113:            // to keep track of which variants of classblock, method arrays, field arrays,
0114:            // and method descriptors have been declared
0115:            // see declareClassblock, declareMethodArray, and declareFieldArray
0116:            // respectively
0117:            //
0118:            private java.util.BitSet classblockSizes = new java.util.BitSet();
0119:            private java.util.BitSet runtimeMethodArraySizes = new java.util.BitSet();
0120:            private java.util.BitSet methodArraySizes = new java.util.BitSet();
0121:            private java.util.BitSet compressibleMethodArraySizes = new java.util.BitSet();
0122:            private java.util.BitSet fieldArraySizes = new java.util.BitSet();
0123:
0124:            /*
0125:             * Per-class data that is built up as we
0126:             * print out the various data structures.
0127:             * Rather than trying to pass around both name and size of each,
0128:             * we collect the information here.
0129:             */
0130:            private String classBlockName;
0131:            private String constantPoolName;
0132:            private int constantPoolSize;
0133:            private String methodArrayName;
0134:            private int methodTableSize;
0135:            private String checkedExceptionName;
0136:            private String interfaceTableName;
0137:            private String fieldTableName;
0138:            private int fieldTableSize;
0139:
0140:            /* for statistics only */
0141:            int ncodebytes;
0142:            int ncatchframes;
0143:            int nmethods;
0144:            int nfields;
0145:            int nconstants;
0146:            int njavastrings;
0147:            int ninnerclasses;
0148:            int nWritableMethodBlocks;
0149:            int nClassesWithWritableMethodBlocks;
0150:            int nClinits;
0151:            int nMethodsWithCheckinitInvokes;
0152:            int nTotalMethods; /* number of total romized methods */
0153:
0154:            private CVMMethodStats methStats = new CVMMethodStats();
0155:
0156:            public CVMWriter() {
0157:                initInfo = new CVMInitInfo();
0158:                initInfoForMBs = new CVMInitInfo();
0159:
0160:                stringTable = new CVMStringTable(initInfo);
0161:            }
0162:
0163:            public void init(boolean classDebug, boolean lossless,
0164:                    ClassnameFilterList nativeTypes, boolean verbose,
0165:                    int maxSegmentSize, boolean mutableMBs) {
0166:                this .verbose = verbose;
0167:                this .classDebug = classDebug;
0168:                this .lossless = lossless;
0169:                this .nativeTypes = nativeTypes;
0170:                this .mutableMBs = mutableMBs;
0171:
0172:                if (maxSegmentSize > 0) {
0173:                    this .segmentedOutput = true;
0174:                    this .maxClasses = maxSegmentSize;
0175:                } else {
0176:                    this .segmentedOutput = false;
0177:                }
0178:            }
0179:
0180:            // If attribute starts with attributeName, then parse the rest of the
0181:            // string as a list of classes.
0182:            private boolean parseClassListAttribute(String attributeName,
0183:                    String attribute, ClassnameFilter filter) {
0184:                if (!attribute.startsWith(attributeName))
0185:                    return false;
0186:                String val = attribute.substring(attributeName.length());
0187:                java.util.StringTokenizer tkn = new java.util.StringTokenizer(
0188:                        val, " ,", false);
0189:                while (tkn.hasMoreTokens()) {
0190:                    String classname = tkn.nextToken().replace('.', '/');
0191:                    filter.includeName(classname);
0192:                }
0193:                return true;
0194:            }
0195:
0196:            private boolean isClassInvisible(String classname) {
0197:                return invisibleClassList.accept(null, classname);
0198:            }
0199:
0200:            private boolean isClassCNI(String classname) {
0201:                // compare against interned string
0202:                return nativeTypes.isType(classname, "CNI");
0203:            }
0204:
0205:            private boolean isClassJNI(String classname) {
0206:                // compare against interned string
0207:                return nativeTypes.isType(classname, "JNI");
0208:            }
0209:
0210:            public boolean setAttribute(String attribute) {
0211:                if (parseClassListAttribute("invisible=", attribute,
0212:                        invisibleClassList)) {
0213:                    return true;
0214:                } else if (attribute.equals("noClassLoading")) {
0215:                    classLoading = false;
0216:                    return true;
0217:                } else if (attribute.equals("noPureCode")) {
0218:                    noPureCode = true;
0219:                    return true;
0220:                } else
0221:                    return false; // no attribute by this name.
0222:            }
0223:
0224:            /*
0225:             * If this is a simple, unsegmented output file, then
0226:             * the file name given is the name of the C file, from which
0227:             * we compute the .h file, crudely. We open them here.
0228:             *
0229:             * But if this is a segmented output job, then the name given
0230:             * serves as a prefix, and we open a whole bunch of files and
0231:             * set up a whole bunch of state:
0232:             *		filename+"List"  - file containing names of all .c files generated
0233:             *				   opened as listOut;
0234:             *		filename+".h"    - header file, as usual
0235:             *		filename+"Aux.c" - file containing all type, string, and other miscellanious
0236:             *				   generated stuff.
0237:             *				   opened as auxOut;
0238:             *		filename+"Class"+n+".c" - files containing directly class-related data,
0239:             *				   whole classes, and a max of this.maxClasses of them
0240:             *				   apiece.
0241:             */
0242:            public boolean open(String filename) {
0243:                if (classOut != null)
0244:                    close();
0245:                outputFileName = filename;
0246:                if (!segmentedOutput) {
0247:                    /* old-fashioned, single output case */
0248:                    if (filename == null) {
0249:                        xxx = System.out;
0250:                        headerFileName = "jcc.output.h";
0251:                    } else {
0252:                        try {
0253:                            xxx = new java.io.FileOutputStream(filename);
0254:                        } catch (java.io.IOException e) {
0255:                            failureMode = e;
0256:                            return false;
0257:                        }
0258:                        headerFileName = filename + ".h";
0259:                    }
0260:                    try {
0261:                        classOut = auxOut = new CCodeWriter(xxx);
0262:                        yyy = new java.io.FileOutputStream(headerFileName);
0263:                        headerOut = new CCodeWriter(yyy);
0264:
0265:                        globalHeaderFileName = filename + "Globals.h";
0266:                        www = new java.io.FileOutputStream(globalHeaderFileName);
0267:                        globalHeaderOut = new CCodeWriter(www);
0268:                    } catch (java.io.IOException e) {
0269:                        failureMode = e;
0270:                        return false;
0271:                    }
0272:                    writeHeaderPrologue(headerOut);
0273:                    writeGlobalHeaderPrologue(globalHeaderOut);
0274:                    writePrologue(classOut);
0275:                    return true;
0276:                } else {
0277:                    /* segmented output.
0278:                     * open the aux file, the first classOut file, the list file and
0279:                     * the header file.
0280:                     */
0281:                    curClasses = 0;
0282:                    nClassfileOut = 0;
0283:                    headerFileName = outputFileName + ".h";
0284:                    try {
0285:                        yyy = new java.io.FileOutputStream(headerFileName);
0286:                        headerOut = new CCodeWriter(yyy);
0287:
0288:                        globalHeaderFileName = outputFileName + "Globals.h";
0289:                        www = new java.io.FileOutputStream(globalHeaderFileName);
0290:                        globalHeaderOut = new CCodeWriter(www);
0291:                        zzz = new java.io.FileOutputStream(filename + "Aux.c");
0292:                        auxOut = new CCodeWriter(zzz);
0293:                        listOut = new BufferedPrintStream(
0294:                                new java.io.FileOutputStream(outputFileName
0295:                                        + "List"));
0296:                        listOut.println(filename + "Aux.c");
0297:                        openNextClassFile();
0298:                    } catch (java.io.IOException e) {
0299:                        failureMode = e;
0300:                        return false;
0301:                    }
0302:                    writeHeaderPrologue(headerOut);
0303:                    writeGlobalHeaderPrologue(globalHeaderOut);
0304:                    writePrologue(auxOut);
0305:
0306:                    /* 
0307:                     * Moved global variables to CVMROMGlobals
0308:                     */
0309:                    auxOut.println("");
0310:                    auxOut
0311:                            .println("/* Moved global variables to CVMROMGlobals.");
0312:                    auxOut
0313:                            .println(" * For each global variable <V> that was originally accessible outside");
0314:                    auxOut
0315:                            .println(" * the generated code, a corresponding constant pointer variable");
0316:                    auxOut
0317:                            .println(" * is provided here that points into the global structure.");
0318:                    auxOut
0319:                            .println(" * (the name <V> has only been changed to <V>ptr for those");
0320:                    auxOut
0321:                            .println(" * variables where the way they are accessed is changed)");
0322:                    auxOut.println(" * ");
0323:                    auxOut
0324:                            .println(" * The size of CVMROMGlobals is provided in a global constant");
0325:                    auxOut
0326:                            .println(" * so that the structure can be copied without including its definition.");
0327:                    auxOut.println(" */");
0328:                    auxOut.println("");
0329:                    auxOut.println("struct CVMROMGlobalState CVMROMGlobals;");
0330:                    auxOut
0331:                            .println("const int CVMROMGlobalsSize = sizeof(CVMROMGlobals);");
0332:                    auxOut.println("");
0333:                    auxOut
0334:                            .println("CVMTypeIDNamePart * const CVMMemberNameHash = CVMROMGlobals.CVMMemberNameHash;");
0335:                    auxOut
0336:                            .println("CVMTypeIDTypePart * const CVMMethodTypeHash = CVMROMGlobals.CVMMethodTypeHash;");
0337:                    auxOut
0338:                            .println("struct sigForm ** const CVMformTablePtr = &CVMROMGlobals.CVMformTable;");
0339:                    auxOut
0340:                            .println("struct pkg * const CVM_ROMpackages = CVMROMGlobals.CVM_ROMpackages;");
0341:                    auxOut
0342:                            .println("struct pkg ** const CVM_pkgHashtable = CVMROMGlobals.CVM_pkgHashtable;");
0343:                    auxOut
0344:                            .println("struct java_lang_Class * const CVM_ROMClassBlocks = CVMROMGlobals.CVM_ROMClassBlocks;");
0345:                    auxOut
0346:                            .println("struct java_lang_Class * const CVM_ROMClasses = CVMROMGlobals.CVM_ROMClasses;");
0347:                    auxOut
0348:                            .println("CVMAddr * const CVM_staticData = CVMROMGlobals.CVM_staticData;");
0349:                    auxOut
0350:                            .println("struct java_lang_String * const CVM_ROMStrings = CVMROMGlobals.CVM_ROMStrings;");
0351:                    auxOut
0352:                            .println("#if defined(CVM_JIT) && defined(CVM_MTASK)");
0353:                    auxOut
0354:                            .println("CVMUint16 * const CVMROMMethodInvokeCosts = CVMROMGlobals.CVMROMMethodInvokeCosts;");
0355:                    auxOut.println("#endif");
0356:                    auxOut.println("");
0357:
0358:                    return true;
0359:                }
0360:            }
0361:
0362:            private void openNextClassFile() throws java.io.IOException {
0363:                if (classOut != null) {
0364:                    classOut.close();
0365:                }
0366:                String newName = outputFileName + (nClassfileOut++) + ".c";
0367:                xxx = new java.io.FileOutputStream(newName);
0368:                classOut = new CCodeWriter(xxx);
0369:                listOut.println(newName);
0370:                writePrologue(classOut);
0371:            }
0372:
0373:            public void close() {
0374:                if (classOut != null) {
0375:                    classOut.close();
0376:                }
0377:                if (auxOut != null && auxOut != classOut) {
0378:                    auxOut.close();
0379:                }
0380:                auxOut = null;
0381:                classOut = null;
0382:                if (listOut != null) {
0383:                    listOut.close();
0384:                    listOut = null;
0385:                }
0386:                if (headerOut != null) {
0387:                    /* 
0388:                     * Added header file for globals
0389:                     */
0390:                    writeHeaderEpilogue(headerOut);
0391:                    headerOut.close();
0392:                    headerOut = null;
0393:                }
0394:                /* 
0395:                 * Added header file for globals
0396:                 */
0397:                if (globalHeaderOut != null) {
0398:                    writeGlobalHeaderEpilogue(globalHeaderOut);
0399:                    globalHeaderOut.close();
0400:                    globalHeaderOut = null;
0401:                }
0402:                outputFileName = null;
0403:                return;
0404:            }
0405:
0406:            public void printError(java.io.PrintStream o) {
0407:                if (failureMode != null) {
0408:                    failureMode.printStackTrace(o);
0409:                }
0410:            }
0411:
0412:            protected void declare(String declaration,
0413:                    BufferedPrintStream curOut) {
0414:                headerOut.print("extern ");
0415:                headerOut.print(declaration);
0416:                headerOut.write(';');
0417:                headerOut.write('\n');
0418:                curOut.print(declaration);
0419:            }
0420:
0421:            public static String getUTF(UnicodeConstant u) {
0422:                return u.toUTF();
0423:            }
0424:
0425:            /*
0426:             * For Java methods,
0427:             * write out the structure which will be initialized with a
0428:             * JavaMethodDescriptor and its associated structures: code array,
0429:             * line numbers, exceptions, local variables
0430:             */
0431:            private void writeCode(CVMMethodInfo meth) {
0432:                MethodInfo mi = meth.method;
0433:                LineNumberTableEntry[] lntab = mi.getLineNumberTable();
0434:                LocalVariableTableEntry[] locvartab = mi
0435:                        .getLocalVariableTable();
0436:
0437:                int codeLengthRoundup = (mi.code.length + 3) & ~3;
0438:                int nTryCatch = (mi.exceptionTable == null) ? 0
0439:                        : mi.exceptionTable.length;
0440:                int nLineNumbers = (classDebug && lntab != null) ? lntab.length
0441:                        : 0;
0442:                int nLocals = (classDebug && locvartab != null) ? locvartab.length
0443:                        : 0;
0444:
0445:                String codeBlockName = meth.getNativeName();
0446:                String descriptorTypeTag = codeBlockName + "MDType";
0447:
0448:                CCodeWriter declareOut;
0449:
0450:                boolean impureCode = noPureCode || !meth.isCodePure();
0451:
0452:                classOut.println("\n/* Code block for "
0453:                        + meth.method.qualifiedName() + " */");
0454:
0455:                /*
0456:                 * Declare the structure which will be initialized with a
0457:                 * JavaMethodDescriptor and its associated structures: code array,
0458:                 * line numbers, exceptions, local variables
0459:                 * Unlike several of the other structures, we do not bother remembering
0460:                 * and reusing prior definitions -- there are so many dimensions it doesn't
0461:                 * see worthwhile.
0462:                 * In fact, the only reason this is not an anonimous structure is the
0463:                 * case where it has to be writable and initialized, for JVMTI.
0464:                 */
0465:                if (!impureCode) {
0466:                    // this might as well be static since there will be
0467:                    // no external references to it
0468:                    classOut.print("STATIC ");
0469:                    declareOut = classOut;
0470:                } else {
0471:                    headerOut.print("extern ");
0472:                    declareOut = headerOut;
0473:                }
0474:
0475:                declareOut.print("const struct ");
0476:                declareOut.print(descriptorTypeTag);
0477:                declareOut.println(" {\n    union {");
0478:                declareOut.println("        CVMJavaMethodDescriptor jmd;");
0479:                declareOut.println("        CVMUint"
0480:                        + ((meth.alignment() == 1) ? "8" : "32")
0481:                        + " align;\n    } u;");
0482:                declareOut.println("    CVMUint8 data[" + codeLengthRoundup
0483:                        + "];");
0484:                if (nTryCatch != 0) {
0485:                    declareOut
0486:                            .println("    CVMExceptionHandler exceptionTable["
0487:                                    + nTryCatch + "];");
0488:                }
0489:                if (nLineNumbers != 0) {
0490:                    declareOut
0491:                            .println("    CVMLineNumberEntry lineNumberTable["
0492:                                    + nLineNumbers + "];");
0493:                }
0494:                if (nLocals != 0) {
0495:                    declareOut
0496:                            .println("    CVMLocalVariableEntry localVariableTable["
0497:                                    + nLocals + "];");
0498:                }
0499:                declareOut.print("} ");
0500:
0501:                /*
0502:                 * Now we have the shape of the data we need to supply the data itself
0503:                 * (themselves?)
0504:                 *
0505:                 * EITHER the MD has to be writable. in thise case the declaration above
0506:                 * was to the header file. Append to it the names of the master and
0507:                 * the working copy, emit the master, reserve space for the copy,
0508:                 * and don't forget the initialization instructions.
0509:                 *
0510:                 * OR the MD is read-only, const, so this is the thing itself
0511:                 */
0512:
0513:                if (impureCode) {
0514:                    declareOut.print(codeBlockName);
0515:                    declareOut.print("Master;\n");
0516:
0517:                    declareOut.print(" extern struct " + descriptorTypeTag);
0518:                    declareOut.write(' ');
0519:                    declareOut.println(codeBlockName);
0520:                    declareOut.println(";");
0521:
0522:                    classOut.print("struct " + descriptorTypeTag);
0523:                    classOut.write(' ');
0524:                    classOut.println(codeBlockName);
0525:                    classOut.println(";");
0526:
0527:                    classOut.print("const struct ");
0528:                    classOut.print(descriptorTypeTag);
0529:                    classOut.write(' ');
0530:                    classOut.print(codeBlockName);
0531:                    classOut.print("Master");
0532:
0533:                    initInfo.addInfo("&" + codeBlockName + "Master", "&"
0534:                            + codeBlockName, "sizeof( struct "
0535:                            + descriptorTypeTag + ")");
0536:                } else {
0537:                    classOut.print(codeBlockName);
0538:                }
0539:
0540:                classOut.print(" = {\n    { CVM_INIT_JAVA_METHOD_DESCRIPTOR(");
0541:                /*
0542:                 * Make sure locals are big enough for any return value.
0543:                 */
0544:                classOut.print(mi.stack + ", " + Math.max(2, mi.locals));
0545:                classOut.print(", ");
0546:                if (meth.codeHasJsr()) {
0547:                    classOut.print("CVM_JMD_MAY_NEED_REWRITE|");
0548:                    if (meth.alignment() != 1) {
0549:                        classOut.print("CVM_JMD_NEEDS_ALIGNMENT|");
0550:                    }
0551:                }
0552:                if (meth.isStrictFP()) {
0553:                    classOut.print("CVM_JMD_STRICT|");
0554:                }
0555:                classOut.print("0, ");
0556:                classOut.print(nTryCatch + ", " + mi.code.length);
0557:                classOut.print(", " + nLineNumbers + ", " + nLocals);
0558:                classOut.print(") },\n    {");
0559:
0560:                // output the code array
0561:                int j = 99;
0562:                byte[] methodCode = mi.code;
0563:                int l = methodCode.length;
0564:                for (int i = 0; i < l; i++) {
0565:                    if (j >= 12) {
0566:                        classOut.print("\n\t");
0567:                        j = 1;
0568:                    } else {
0569:                        j += 1;
0570:                    }
0571:                    classOut.printHexInt(methodCode[i] & 0xff);
0572:                    classOut.print(",");
0573:                }
0574:                classOut.print("\n    }");
0575:                ncodebytes += mi.code.length;
0576:
0577:                // output the CVMExceptionHandler[] (catch frames)
0578:                if (nTryCatch != 0) {
0579:                    classOut.println(",\n    {");
0580:                    for (int i = 0; i < nTryCatch; i++) {
0581:                        ExceptionEntry e = mi.exceptionTable[i];
0582:                        classOut.println("\t{ " + e.startPC + ", " + e.endPC
0583:                                + ", " + e.handlerPC + ", "
0584:                                + (e.catchType == null ? 0 : e.catchType.index)
0585:                                + "},");
0586:                    }
0587:                    classOut.print("    }");
0588:                    ncatchframes += nTryCatch;
0589:                }
0590:
0591:                // output the CVMLineNumberEntry[]
0592:                if (nLineNumbers != 0) {
0593:                    classOut.println(",\n    {");
0594:                    for (int i = 0; i < nLineNumbers; i++) {
0595:                        LineNumberTableEntry e = lntab[i];
0596:                        classOut.println("\t{ " + e.startPC + ", "
0597:                                + e.lineNumber + "},");
0598:                    }
0599:                    classOut.print("    }");
0600:                }
0601:
0602:                // output the CVMLocalVariableEntry[]
0603:                if (nLocals != 0) {
0604:                    classOut.println(",\n    {");
0605:                    for (int i = 0; i < nLocals; i++) {
0606:                        LocalVariableTableEntry e = locvartab[i];
0607:                        int typeid = CVMDataType.parseSignature(getUTF(e.sig));
0608:                        int nameid = CVMMemberNameEntry
0609:                                .lookupEnter(getUTF(e.name));
0610:                        classOut.println("\t{ " + e.pc0 + ", " + e.length
0611:                                + ", " + e.slot + ", RAW_TYPEID_NAME_PART(0x"
0612:                                + Integer.toHexString(nameid)
0613:                                + "), RAW_TYPEID_TYPE_PART(0x"
0614:                                + Integer.toHexString(typeid) + ")},");
0615:                    }
0616:                    classOut.print("    }");
0617:                }
0618:
0619:                classOut.println("\n};");
0620:
0621:            }
0622:
0623:            //
0624:            // The cb repeats every 'cbRepeat' entries in MethodArray's and
0625:            // FieldArray's
0626:            //
0627:            static final int cbRepeat = 256;
0628:
0629:            private void handleMethodArrayDecl(String flavorName, int nmethods) {
0630:                // need to declare a structure containing a classblock pointer
0631:                // plus "nmethods" CVMMethodBlock structures
0632:                int i;
0633:                headerOut.print(flavorName + " {");
0634:                if (nmethods > cbRepeat)
0635:                    headerOut.println();
0636:                int numMethodArrays = (nmethods - 1) / cbRepeat + 1;
0637:                for (i = 1; i <= numMethodArrays; i++) {
0638:                    int nmethods2; // # methods in this method array
0639:                    if (i == numMethodArrays) {
0640:                        nmethods2 = (nmethods - 1) % cbRepeat + 1;
0641:                    } else {
0642:                        nmethods2 = cbRepeat;
0643:                    }
0644:                    headerOut
0645:                            .println(" CVMClassBlock const *cb" + i + ";"
0646:                                    + " CVMMethodBlock mb" + i + "["
0647:                                    + nmethods2 + "];");
0648:                    if (nmethods > cbRepeat) {
0649:                        headerOut.println();
0650:                    }
0651:                }
0652:                headerOut.println(" };");
0653:            }
0654:
0655:            private void declareMethodArray(CVMClass c, boolean writeable,
0656:                    boolean compressible) {
0657:                String this TableName = c.getNativeName() + "_methods";
0658:                String tableAddress = "&" + this TableName;
0659:                int nmethods = c.methods.length;
0660:                String methodArrayFlavor = "struct CVMMethodArray" + nmethods;
0661:                String methodArrayImmutFlavor = "struct CVMMethodArrayImmut"
0662:                        + nmethods;
0663:                String methodArrayImmutCompFlavor = "struct CVMMethodArrayImmutCompressed"
0664:                        + nmethods;
0665:                String immutFlavor;
0666:                String immutableType;
0667:                java.util.BitSet methArrSizes;
0668:
0669:                /* count the total number of romized methods */
0670:                nTotalMethods += nmethods;
0671:
0672:                if (compressible) {
0673:                    immutableType = "CVMMethodBlockImmutableCompressed";
0674:                    immutFlavor = methodArrayImmutCompFlavor;
0675:                    methArrSizes = compressibleMethodArraySizes;
0676:                } else {
0677:                    immutableType = "CVMMethodBlockImmutable";
0678:                    immutFlavor = methodArrayImmutFlavor;
0679:                    methArrSizes = methodArraySizes;
0680:                }
0681:
0682:                /*
0683:                 * Declare the runtime typedef
0684:                 */
0685:                if (!runtimeMethodArraySizes.get(nmethods)) {
0686:                    handleMethodArrayDecl(methodArrayFlavor, nmethods);
0687:                    runtimeMethodArraySizes.set(nmethods);
0688:                }
0689:
0690:                /*
0691:                 * And now, declare the proper immutable type
0692:                 */
0693:                if (!methArrSizes.get(nmethods)) {
0694:                    /* The immutable version is easy. Just bundle all the immutable
0695:                       parts together, and let the initializer take care
0696:                       of the methods arrays */
0697:                    headerOut.print(immutFlavor + " {");
0698:                    headerOut.println(" CVMClassBlock const *cb; "
0699:                            + immutableType + " mb[" + nmethods + "];");
0700:                    headerOut.println(" };");
0701:                    methArrSizes.set(nmethods);
0702:                }
0703:
0704:                if (writeable) {
0705:                    /*
0706:                     * Declare actual array, record copying information.
0707:                     * What we're about to initialize is the read-only master.
0708:                     */
0709:                    String masterName = this TableName + "Master";
0710:
0711:                    /* 
0712:                     * Moved global variables to CVMROMGlobals.
0713:                     */
0714:                    /*
0715:                    declare(methodArrayFlavor+" "+thisTableName, classOut); 
0716:                    classOut.println(";");
0717:                     */
0718:                    globalHeaderOut.println("    " + methodArrayFlavor + " "
0719:                            + this TableName + ";");
0720:                    initInfoForMBs.addInfo("&" + masterName);
0721:                    declare("const " + immutFlavor + " " + masterName, classOut);
0722:                } else {
0723:                    declare("const " + methodArrayFlavor + " " + this TableName,
0724:                            classOut);
0725:                }
0726:                /* 
0727:                 * Moved globals to CVMROMGlobals.  For classes without
0728:                 * writeable methods, there is (still) a constant global
0729:                 * variable <class>_methods - nothing has changed.  For
0730:                 * classes with writeable methods, the <class>_methods
0731:                 * variable lives in the CVMROMGlobals structure.  
0732:                 */
0733:                if (writeable) {
0734:                    methodArrayName = "&CVMROMGlobals." + this TableName;
0735:                } else {
0736:                    methodArrayName = tableAddress;
0737:                }
0738:                methodTableSize = nmethods;
0739:            }
0740:
0741:            //
0742:            // Find out variations of several method components to see whether
0743:            // compression opportunities exist.
0744:            //
0745:            // 1) Look for (argsSize, invokerIdx, accessFlags) triples. These
0746:            // don't vary much, so we can encode commonly occurring
0747:            // variants within 8-bits.
0748:            //
0749:            // 2) Check whether the method table index and checkedExceptionsOffset
0750:            // can each be encoded in a byte.
0751:            //
0752:            // If #1 and #2 hold, we can shave off a word from the immutable method
0753:            // block encoding.
0754:            //
0755:            void analyzeMethodsForCompression(CVMClass c) {
0756:                CVMMethodInfo m[] = c.methods;
0757:                int nCheckedExceptions = 0;
0758:                int currCheckedException = 0;
0759:                int checkedExceptionVector[];
0760:                if ((m == null) || (m.length == 0)) {
0761:                    /* Nothing to do */
0762:                    return;
0763:                }
0764:                int nmethod = m.length;
0765:                //
0766:                // Traverse all methods, and look for opportunities. If any
0767:                // one method in the methods of a class is not compressible,
0768:                // the entire method array is expanded in the "long" form
0769:                //
0770:                for (int i = 0; i < nmethod; i++) {
0771:                    CVMMethodInfo meth = m[i];
0772:                    MethodInfo mi = meth.method;
0773:                    if (mi.exceptionsThrown != null) {
0774:                        int n = mi.exceptionsThrown.length;
0775:                        if (n != 0)
0776:                            nCheckedExceptions += n + 1; // "1" is for the count word.
0777:                    }
0778:                }
0779:                //
0780:                // if any methods declare that they throw any exceptions,
0781:                // we need to construct the exception vector.
0782:                if (nCheckedExceptions == 0) {
0783:                    checkedExceptionVector = null;
0784:                } else {
0785:                    // Ensure that item 0 in this array is always unused.
0786:                    // See classes.h.
0787:                    nCheckedExceptions++;
0788:                    checkedExceptionVector = new int[nCheckedExceptions];
0789:                    checkedExceptionVector[0] = 0;
0790:                    currCheckedException = 1;
0791:                }
0792:
0793:                for (int i = 0; i < nmethod; i++) {
0794:                    CVMMethodInfo meth = m[i];
0795:
0796:                    //
0797:                    // Item #1
0798:                    //
0799:                    int access = meth.CVMflags();
0800:
0801:                    boolean synchro = (access & CVM_METHOD_ACC_SYNCHRONIZED) != 0;
0802:                    boolean isNative = (access & CVM_METHOD_ACC_NATIVE) != 0;
0803:                    boolean isAbstract = (access & CVM_METHOD_ACC_ABSTRACT) != 0;
0804:
0805:                    //
0806:                    // Item #2
0807:                    //
0808:                    String invoker = isAbstract ? "CVM_INVOKE_ABSTRACT_METHOD"
0809:                            : isNative ? (isClassCNI(c.ci.className) ? "CVM_INVOKE_CNI_METHOD"
0810:                                    : (synchro ? "CVM_INVOKE_JNI_SYNC_METHOD"
0811:                                            : "CVM_INVOKE_JNI_METHOD"))
0812:                                    : (synchro ? "CVM_INVOKE_JAVA_SYNC_METHOD"
0813:                                            : "CVM_INVOKE_JAVA_METHOD");
0814:
0815:                    //
0816:                    // note the offset in the exception array,
0817:                    // and add to that array as necessary.
0818:                    //
0819:                    int exceptions;
0820:                    if ((meth.method.exceptionsThrown != null)
0821:                            && (meth.method.exceptionsThrown.length != 0)) {
0822:                        ClassConstant thrown[] = meth.method.exceptionsThrown;
0823:                        int net = thrown.length;
0824:                        exceptions = currCheckedException;
0825:                        checkedExceptionVector[currCheckedException++] = net;
0826:                        for (int j = 0; j < net; j++) {
0827:                            checkedExceptionVector[currCheckedException++] = thrown[j].index;
0828:                        }
0829:                    } else {
0830:                        // Note we have changed this from ((unsigned short)
0831:                        // -1) to 0 to be consistent with the documentation in
0832:                        // classes.h. A checkedExceptionsOffset of 0 indicates
0833:                        // no checked exceptions for the method. Also see the
0834:                        // allocation of the checkedExceptionVector above.
0835:                        exceptions = 0;
0836:                    }
0837:                    //
0838:                    // Item #3
0839:                    //
0840:                    int argssize = meth.method.argsSize;
0841:
0842:                    int tableIndex = meth.methodOffset();
0843:
0844:                    //
0845:                    // Remember these items
0846:                    // We won't know whether a class is compressible
0847:                    // until after all the triples for all methods have been seen
0848:                    //
0849:                    methStats.record(argssize, invoker, access);
0850:
0851:                    // 
0852:                    // Also see whether the method table index and
0853:                    // checkedExceptionsOffset are encodable in one byte each.
0854:                    //
0855:                    if (tableIndex >= 256) {
0856:                        c.setCompressible(false);
0857:                    }
0858:                    if (exceptions >= 256) {
0859:                        c.setCompressible(false);
0860:                    }
0861:                }
0862:            }
0863:
0864:            void writeMethods(CVMClass c) {
0865:                boolean isCompressible = c.isCompressible();
0866:                String cbname_comma = "&" + cbName(c) + ",";
0867:                CVMMethodInfo m[] = c.methods;
0868:                int nCheckedExceptions = 0;
0869:                int currCheckedException = 0;
0870:                int checkedExceptionVector[];
0871:                boolean writableMethods = mutableMBs;
0872:                if ((m == null) || (m.length == 0)) {
0873:                    methodArrayName = "0";
0874:                    checkedExceptionName = "0";
0875:                    methodTableSize = 0;
0876:                    return;
0877:                }
0878:                int nmethod = m.length;
0879:                String this TableName = c.getNativeName() + "_methods";
0880:                String this ExceptionName = null;
0881:                for (int i = 0; i < nmethod; i++) {
0882:                    CVMMethodInfo meth = m[i];
0883:                    MethodInfo mi = meth.method;
0884:                    if (mi.exceptionsThrown != null) {
0885:                        int n = mi.exceptionsThrown.length;
0886:                        if (n != 0)
0887:                            nCheckedExceptions += n + 1; // "1" is for the count word.
0888:                    }
0889:                    if (mi.code != null) {
0890:                        writeCode(meth);
0891:                    }
0892:                    if (meth.codeHasJsr()) {
0893:                        writableMethods = true;
0894:                    }
0895:                }
0896:                //
0897:                // if any methods declare that they throw any exceptions,
0898:                // we need to construct the exception vector.
0899:                if (nCheckedExceptions == 0) {
0900:                    checkedExceptionName = "0";
0901:                    checkedExceptionVector = null;
0902:                } else {
0903:                    this ExceptionName = c.getNativeName() + "_throws";
0904:                    checkedExceptionName = this ExceptionName;
0905:                    // Ensure that item 0 in this array is always unused.
0906:                    // See classes.h.
0907:                    nCheckedExceptions++;
0908:                    checkedExceptionVector = new int[nCheckedExceptions];
0909:                    checkedExceptionVector[0] = 0;
0910:                    currCheckedException = 1;
0911:                }
0912:                boolean emittedNativeHeader = false;
0913:                //
0914:                // Look to see whether we can compact this
0915:                //
0916:                for (int i = 0; i < nmethod; i++) {
0917:                    CVMMethodInfo meth = m[i];
0918:                    int access = meth.CVMflags();
0919:                    if (!emittedNativeHeader
0920:                            && ((access & CVM_METHOD_ACC_NATIVE) != 0)) {
0921:                        String subdir = isClassCNI(c.ci.className) ? "cni/"
0922:                                : "jni/";
0923:                        headerOut.println("#include \"generated/" + subdir
0924:                                + Util.convertToClassName(c.ci.className)
0925:                                + ".h\"");
0926:                        emittedNativeHeader = true;
0927:                    }
0928:                    boolean synchro = (access & CVM_METHOD_ACC_SYNCHRONIZED) != 0;
0929:                    boolean isNative = (access & CVM_METHOD_ACC_NATIVE) != 0;
0930:                    boolean isAbstract = (access & CVM_METHOD_ACC_ABSTRACT) != 0;
0931:
0932:                    String invoker = isAbstract ? "CVM_INVOKE_ABSTRACT_METHOD"
0933:                            : isNative ? (isClassCNI(c.ci.className) ? "CVM_INVOKE_CNI_METHOD"
0934:                                    : (synchro ? "CVM_INVOKE_JNI_SYNC_METHOD"
0935:                                            : "CVM_INVOKE_JNI_METHOD"))
0936:                                    : (synchro ? "CVM_INVOKE_JAVA_SYNC_METHOD"
0937:                                            : "CVM_INVOKE_JAVA_METHOD");
0938:                    int argssize = meth.method.argsSize;
0939:
0940:                    CVMMethodStats.Entry entry = methStats.lookup(argssize,
0941:                            invoker, access);
0942:                    //
0943:                    // Cannot encode in one byte, therefore cannot compress
0944:                    //
0945:                    if (entry.getIdx() >= 256) {
0946:                        c.setCompressible(false);
0947:                    }
0948:                    meth.statsEntry = entry;
0949:                }
0950:
0951:                //
0952:                // Update the compressibility of class c
0953:                //
0954:                isCompressible = isCompressible && c.isCompressible();
0955:
0956:                //
0957:                // isCompressible cannot be true if the mb's are to be read-only
0958:                //
0959:                isCompressible = isCompressible && writableMethods;
0960:
0961:                // if any method has a JSR, then its method block, and thus
0962:                // all of them, must be writable, so we can replace its code, bundled
0963:                // with its JavaMethodDescriptor.
0964:                declareMethodArray(c, writableMethods, isCompressible);
0965:                String cbDeclaration;
0966:
0967:                if (isCompressible) {
0968:                    cbDeclaration = "CVM_INIT_METHODARRAY_CB_WITH_COMPRESSED_MBS";
0969:                } else {
0970:                    cbDeclaration = "CVM_INIT_METHODARRAY_CB_WITH_UNCOMPRESSED_MBS";
0971:                }
0972:
0973:                classOut.print(" = {\n\t" + cbDeclaration + "(&"
0974:                        + classBlockName + "),\n\t{\n");
0975:
0976:                for (int i = 0; i < nmethod; i++) {
0977:                    CVMMethodInfo meth = m[i];
0978:                    if (meth.method.hasCheckinits) {
0979:                        nMethodsWithCheckinitInvokes++;
0980:                    }
0981:                    int mbIndex = i % cbRepeat;
0982:                    int typeid = meth.sigType.entryNo;
0983:                    int nameid = CVMMemberNameEntry
0984:                            .lookupEnter(getUTF(meth.method.name));
0985:                    String nameAndType = "RAW_TYPEID(0x"
0986:                            + Integer.toHexString(nameid) + ", 0x"
0987:                            + Integer.toHexString(typeid) + ")";
0988:                    int access = meth.CVMflags();
0989:
0990:                    boolean synchro = (access & CVM_METHOD_ACC_SYNCHRONIZED) != 0;
0991:                    boolean isNative = (access & CVM_METHOD_ACC_NATIVE) != 0;
0992:                    boolean isAbstract = (access & CVM_METHOD_ACC_ABSTRACT) != 0;
0993:
0994:                    String invoker = meth.statsEntry.getInvoker();
0995:
0996:                    /* By default let interpreter do invocation in all
0997:                       except native methods. Compilation might change
0998:                       invoker function */
0999:                    String jitInvoker = isNative ? (isClassCNI(c.ci.className) ? "CVMCCMinvokeCNIMethod"
1000:                            : "CVMCCMinvokeJNIMethod")
1001:                            : "CVMCCMletInterpreterDoInvoke";
1002:
1003:                    //
1004:                    // note the offset in the exception array,
1005:                    // and add to that array as necessary.
1006:                    int exceptions;
1007:                    if ((meth.method.exceptionsThrown != null)
1008:                            && (meth.method.exceptionsThrown.length != 0)) {
1009:                        ClassConstant thrown[] = meth.method.exceptionsThrown;
1010:                        int net = thrown.length;
1011:                        exceptions = currCheckedException;
1012:                        checkedExceptionVector[currCheckedException++] = net;
1013:                        for (int j = 0; j < net; j++) {
1014:                            checkedExceptionVector[currCheckedException++] = thrown[j].index;
1015:                        }
1016:                    } else {
1017:                        // Note we have changed this from ((unsigned short)
1018:                        // -1) to 0 to be consistent with the documentation in
1019:                        // classes.h. A checkedExceptionsOffset of 0 indicates
1020:                        // no checked exceptions for the method. Also see the
1021:                        // allocation of the checkedExceptionVector above.
1022:                        exceptions = 0;
1023:                    }
1024:                    int argssize = meth.method.argsSize;
1025:                    int tableIndex = meth.methodOffset();
1026:
1027:                    /* 
1028:                     * method offsets are always mod 'cbRepeat' and we have to
1029:                     * emit a cb entry before each block of 'cbRepeat'
1030:                     * methods. 
1031:                     */
1032:                    if ((mbIndex == 0) && (i != 0) && !isCompressible
1033:                            && !writableMethods) {
1034:                        // Output the repeated cb only if we are emitting read-only
1035:                        // method blocks.
1036:                        classOut.print("\t},\n");
1037:                        classOut.print("\t&" + classBlockName + ",\n\t{\n");
1038:                    }
1039:
1040:                    if (isCompressible) {
1041:                        // The C compiler checks that the values here are
1042:                        // really compressed within the proper sizes. We get
1043:                        // warnings if we exceed the maximum width for a given
1044:                        // data field.
1045:                        //
1046:                        // entryIdx encapsulates argssize, invoker, and access flags
1047:                        int entryIdx = meth.statsEntry.getIdx();
1048:                        classOut
1049:                                .print("	CVM_INIT_METHODBLOCK_IMMUTABLE_COMPRESSED("
1050:                                        + cbname_comma
1051:                                        + nameAndType
1052:                                        + ","
1053:                                        + tableIndex
1054:                                        + ","
1055:                                        + entryIdx
1056:                                        + ","
1057:                                        + mbIndex + "," + exceptions + ",");
1058:                    } else if (writableMethods) {
1059:                        classOut.print("	CVM_INIT_METHODBLOCK_IMMUTABLE("
1060:                                + cbname_comma + nameAndType + "," + tableIndex
1061:                                + "," + argssize + "," + invoker + "," + access
1062:                                + "," + mbIndex + "," + exceptions + ",");
1063:                    } else {
1064:                        classOut.print("	CVM_INIT_METHODBLOCK(" + cbname_comma
1065:                                + jitInvoker + "," + nameAndType + ","
1066:                                + tableIndex + "," + argssize + "," + invoker
1067:                                + "," + access + "," + mbIndex + ","
1068:                                + exceptions + ",");
1069:                    }
1070:
1071:                    if (isAbstract) {
1072:                        classOut.print("(CVMJavaMethodDescriptor*)" + i
1073:                                + "),\n");
1074:                    } else if (isNative) {
1075:                        if (isClassCNI(c.ci.className)) {
1076:                            String jniName = meth.method.getNativeName(true);
1077:                            String eniName = "CNI" + jniName.substring(5);
1078:                            classOut.print("(CVMJavaMethodDescriptor*)&"
1079:                                    + eniName + "),\n");
1080:                        } else {
1081:                            classOut.print("(CVMJavaMethodDescriptor*)&"
1082:                                    + meth.method.getNativeName(true) + "),\n");
1083:                        }
1084:                    } else {
1085:                        classOut.print("&(" + meth.getNativeName()
1086:                                + ".u.jmd)),\n");
1087:                    }
1088:
1089:                }
1090:                classOut.print("}};\n");
1091:                this .nmethods += nmethod;
1092:                if (writableMethods) {
1093:                    nClassesWithWritableMethodBlocks += 1;
1094:                    nWritableMethodBlocks += nmethod;
1095:                }
1096:                //
1097:                // now, if there are any exception-catch clauses
1098:                // that need to be represented, print out the table.
1099:                if (nCheckedExceptions != 0) {
1100:                    classOut.println("STATIC const CVMUint16 "
1101:                            + this ExceptionName + "[] = {");
1102:                    int j = 0;
1103:                    for (int i = 0; i < nCheckedExceptions; i++) {
1104:                        if (j >= 8) {
1105:                            classOut.print("\n    ");
1106:                            j = 0;
1107:                        } else {
1108:                            j += 1;
1109:                        }
1110:                        classOut.print(checkedExceptionVector[i] + ", ");
1111:                    }
1112:                    classOut.println("\n};");
1113:                }
1114:            }
1115:
1116:            /*
1117:             * Write out the InnerClassInfo structure. This structure will contain
1118:             * information about all referenced inner classes.
1119:             */
1120:            private void writeInnerClasses(CVMClass c) {
1121:                //Write information about each inner class contained in this class.
1122:                int innerClassCount = c.ci.innerClassAttr.getInnerClassCount();
1123:                InnerClassAttribute ica = c.ci.innerClassAttr;
1124:                classOut.println("    " + innerClassCount + ", {");
1125:                for (int j = 0; j < innerClassCount; j++) {
1126:                    // write out the indexes and access flags of this inner class.
1127:                    classOut.print("        {");
1128:                    classOut.print(ica.getInnerInfoIndex(j));
1129:                    classOut.write(',');
1130:                    classOut.print(ica.getOuterInfoIndex(j));
1131:                    classOut.write(',');
1132:                    /* innerNameIndex not supported because utf8 cp entries
1133:                     * are not kept around.
1134:                    classOut.print(ica.getInnerNameIndex(j));
1135:                     */
1136:                    classOut.print('0');
1137:                    classOut.write(',');
1138:                    classOut.print(ica.getAccessFlags(j));
1139:                    classOut.print("},\n");
1140:                }
1141:                classOut.println("    }");
1142:                ninnerclasses += innerClassCount;
1143:            }
1144:
1145:            void mungeAllIDsAndWriteExternals(ClassClass classes[]) {
1146:            }
1147:
1148:            private static int CVMDataAccessFlags(int access) {
1149:                int a = 0;
1150:                if ((access & ACC_PUBLIC) != 0)
1151:                    a |= CVM_FIELD_ACC_PUBLIC;
1152:                if ((access & ACC_PRIVATE) != 0)
1153:                    a |= CVM_FIELD_ACC_PRIVATE;
1154:                if ((access & ACC_PROTECTED) != 0)
1155:                    a |= CVM_FIELD_ACC_PROTECTED;
1156:                if ((access & ACC_STATIC) != 0)
1157:                    a |= CVM_FIELD_ACC_STATIC;
1158:                if ((access & ACC_FINAL) != 0)
1159:                    a |= CVM_FIELD_ACC_FINAL;
1160:                if ((access & ACC_VOLATILE) != 0)
1161:                    a |= CVM_FIELD_ACC_VOLATILE;
1162:                if ((access & ACC_TRANSIENT) != 0)
1163:                    a |= CVM_FIELD_ACC_TRANSIENT;
1164:                return a;
1165:            }
1166:
1167:            private void declareFieldArray(CVMClass c) {
1168:                // Note: Should deal with > 255 fields.
1169:                // Today is not that day. Just do the simple case.
1170:                FieldInfo m[] = c.ci.fields;
1171:                int nfields = m.length;
1172:                String this TableName = c.getNativeName() + "_fields";
1173:                String fieldArrayFlavor = "struct CVMFieldArray" + nfields;
1174:                if (!fieldArraySizes.get(nfields)) {
1175:                    // need to declare a structure containing a classblock pointer
1176:                    // plus "nfields" CVMFieldBlock structures
1177:                    int i;
1178:                    headerOut.print(fieldArrayFlavor + " {");
1179:                    if (nfields > cbRepeat)
1180:                        headerOut.println();
1181:                    int numFieldArrays = (nfields - 1) / cbRepeat + 1;
1182:                    for (i = 1; i <= numFieldArrays; i++) {
1183:                        int nfields2; // # fields in this field array
1184:                        if (i == numFieldArrays) {
1185:                            nfields2 = (nfields - 1) % cbRepeat + 1;
1186:                        } else {
1187:                            nfields2 = cbRepeat;
1188:                        }
1189:                        headerOut.print(" CVMClassBlock const *cb" + i + ";"
1190:                                + " CVMFieldBlock fb" + i + "[" + nfields2
1191:                                + "];");
1192:                        if (nfields > cbRepeat) {
1193:                            headerOut.println();
1194:                        }
1195:                    }
1196:                    headerOut.println(" };");
1197:                    fieldArraySizes.set(nfields);
1198:                }
1199:                declare("const " + fieldArrayFlavor + " " + this TableName,
1200:                        classOut);
1201:                fieldTableName = "&" + this TableName;
1202:                fieldTableSize = nfields;
1203:            }
1204:
1205:            void writeFields(CVMClass c) {
1206:                // Note: Should deal with > 255 fields.
1207:                // Today is not that day. Just do the simple case.
1208:                FieldInfo m[] = c.ci.fields;
1209:                if ((m == null) || (m.length == 0)) {
1210:                    fieldTableName = "0";
1211:                    fieldTableSize = 0;
1212:                    return;
1213:                }
1214:                int nfields = m.length;
1215:                declareFieldArray(c);
1216:                classOut.print(" = {\n");
1217:                for (int i = 0; i < nfields; i++) {
1218:                    int fbIndex = i % cbRepeat;
1219:                    FieldInfo f = m[i];
1220:                    int typeid = CVMDataType.parseSignature(getUTF(f.type));
1221:                    int nameid = CVMMemberNameEntry.lookupEnter(getUTF(f.name));
1222:                    String nameAndType = "RAW_TYPEID(0x"
1223:                            + Integer.toHexString(nameid) + ", 0x"
1224:                            + Integer.toHexString(typeid) + ")";
1225:                    //System.out.println( nameAndType+" => "+Integer.toHexString(typeid) );
1226:                    int access = CVMDataAccessFlags(f.access);
1227:                    int offset = f.instanceOffset;
1228:                    /* field offsets are always mod cbRepeat and we have to emit a cb
1229:                     * entry before each block of cbRepeat fields. */
1230:                    if (fbIndex == 0) {
1231:                        if (i != 0) {
1232:                            classOut.print("\t},\n");
1233:                        }
1234:                        classOut.print("\t&" + classBlockName + ",\n\t{\n");
1235:                    }
1236:                    // static members use simple byte offset
1237:                    // instance members include size of header info
1238:                    if (f.isStaticMember()) {
1239:                        classOut.print("	CVM_INIT_FIELDBLOCK(" + nameAndType
1240:                                + "," + access + "," + fbIndex
1241:                                + ", CVM_STATIC_OFFSET(" + offset + ")),\n");
1242:                    } else {
1243:                        classOut.print("	CVM_INIT_FIELDBLOCK(" + nameAndType
1244:                                + "," + access + "," + fbIndex
1245:                                + ", CVM_FIELD_OFFSET(" + offset + ")),\n");
1246:                    }
1247:                }
1248:                classOut.println("}};");
1249:                this .nfields += nfields;
1250:
1251:            }
1252:
1253:            private String methodBlockAddress(MethodInfo mi) {
1254:                CVMMethodInfo em = (CVMMethodInfo) (mi.vmMethodInfo);
1255:                CVMClass ec = (CVMClass) (mi.parent.vmClass);
1256:                int n = mi.index;
1257:                /* 
1258:                 * Moved globals to CVMROMGlobals.  For classes without
1259:                 * writeable methods, there is (still) a constant global
1260:                 * variable <class>_methods - nothing has changed.  For
1261:                 * classes with writeable methods, the <class>_methods
1262:                 * variable lives in the CVMROMGlobals structure. The ability
1263:                 * to determine whether a class has writable methods has been
1264:                 * added to CVMClass.  
1265:                 */
1266:                if (mutableMBs || ec.hasWritableMethods())
1267:                    return "&CVMROMGlobals." + ec.getNativeName()
1268:                            + "_methods.mb" + (n / cbRepeat + 1) + "[" + n
1269:                            % cbRepeat + "]"; // had better not be an interface.
1270:                // had better not be an interface.
1271:                return "&" + ec.getNativeName() + "_methods.mb"
1272:                        + (n / cbRepeat + 1) + "[" + n % cbRepeat + "]";
1273:            }
1274:
1275:            private static String fieldBlockAddress(FieldInfo f) {
1276:                // pretty disgusting.
1277:                // if this is frequent enough, find a better way!
1278:                ClassInfo c = f.parent;
1279:                FieldInfo cf[] = c.fields;
1280:                int n = f.index;
1281:                //for ( n = 0; cf[n] != f; n++ ) // TRY THIS.
1282:                //   ;
1283:                // assume we found it.
1284:                String parentName = ((CVMClass) (c.vmClass)).getNativeName();
1285:                return "&" + parentName + "_fields.fb" + (n / cbRepeat + 1)
1286:                        + "[" + n % cbRepeat + "]";
1287:            }
1288:
1289:            private static final int unresolvedCVMConstantMap[] = {
1290:                    CVM_CONSTANT_Invalid, CVM_CONSTANT_Utf8,
1291:                    CVM_CONSTANT_Invalid,
1292:                    CVM_CONSTANT_Integer | CVM_CONSTANT_POOL_ENTRY_RESOLVED,
1293:                    CVM_CONSTANT_Float | CVM_CONSTANT_POOL_ENTRY_RESOLVED,
1294:                    CVM_CONSTANT_Long | CVM_CONSTANT_POOL_ENTRY_RESOLVED,
1295:                    CVM_CONSTANT_Double | CVM_CONSTANT_POOL_ENTRY_RESOLVED,
1296:                    CVM_CONSTANT_ClassTypeID,
1297:                    CVM_CONSTANT_StringObj | CVM_CONSTANT_POOL_ENTRY_RESOLVED,
1298:                    CVM_CONSTANT_Fieldref, CVM_CONSTANT_Methodref,
1299:                    CVM_CONSTANT_InterfaceMethodref, CVM_CONSTANT_NameAndType };
1300:
1301:            private static final int resolvedCVMConstantMap[] = {
1302:                    CVM_CONSTANT_Invalid,
1303:                    CVM_CONSTANT_Utf8,
1304:                    CVM_CONSTANT_Invalid,
1305:                    CVM_CONSTANT_Integer | CVM_CONSTANT_POOL_ENTRY_RESOLVED,
1306:                    CVM_CONSTANT_Float | CVM_CONSTANT_POOL_ENTRY_RESOLVED,
1307:                    CVM_CONSTANT_Long | CVM_CONSTANT_POOL_ENTRY_RESOLVED,
1308:                    CVM_CONSTANT_Double | CVM_CONSTANT_POOL_ENTRY_RESOLVED,
1309:                    CVM_CONSTANT_ClassBlock | CVM_CONSTANT_POOL_ENTRY_RESOLVED,
1310:                    CVM_CONSTANT_StringObj | CVM_CONSTANT_POOL_ENTRY_RESOLVED,
1311:                    CVM_CONSTANT_FieldBlock | CVM_CONSTANT_POOL_ENTRY_RESOLVED,
1312:                    CVM_CONSTANT_MethodBlock | CVM_CONSTANT_POOL_ENTRY_RESOLVED,
1313:                    CVM_CONSTANT_MethodBlock | CVM_CONSTANT_POOL_ENTRY_RESOLVED,
1314:                    CVM_CONSTANT_NameAndType };
1315:
1316:            private static int CVMconstantTag(ConstantObject c) {
1317:                int t;
1318:                if (c.isResolved()) {
1319:                    t = resolvedCVMConstantMap[c.tag];
1320:                    if (t == CVM_CONSTANT_NameAndType) {
1321:                        String sig = ((NameAndTypeConstant) c).type.string;
1322:                        t = (sig.charAt(0) == SIGC_METHOD) ? CVM_CONSTANT_MethodTypeID
1323:                                : CVM_CONSTANT_FieldTypeID;
1324:                    }
1325:                } else {
1326:                    t = unresolvedCVMConstantMap[c.tag];
1327:                    if (t == CVM_CONSTANT_NameAndType) {
1328:                        String sig = ((NameAndTypeConstant) c).type.string;
1329:                        t = (sig.charAt(0) == SIGC_METHOD) ? CVM_CONSTANT_MethodTypeID
1330:                                : CVM_CONSTANT_FieldTypeID;
1331:                    }
1332:                }
1333:                return t;
1334:            }
1335:
1336:            // return address of this type table.
1337:            private String writeTypeTable(ConstantObject constants[],
1338:                    String name) {
1339:                int clen = constants.length;
1340:                String ttname = name + "_tt";
1341:                auxOut.print("CVMUint8 " + ttname + "[] = { 0,");
1342:                int j = 99;
1343:                for (int i = 1; i < clen; i += constants[i].nSlots) {
1344:                    if (j >= 10) {
1345:                        auxOut.print("\n    ");
1346:                        j = 1;
1347:                    } else {
1348:                        j += 1;
1349:                    }
1350:                    auxOut.print(CVMconstantTag(constants[i]) + ",");
1351:                    if (constants[i].nSlots == 2) {
1352:                        auxOut.print(" 0,"); // 2nd word of 2-word constant 
1353:                        j += 1;
1354:                    }
1355:                }
1356:                auxOut.println("\n};");
1357:                headerOut.println("extern CVMUint8 " + ttname + "[" + clen
1358:                        + "];");
1359:                return "&" + ttname;
1360:            }
1361:
1362:            // return address of this array Info.
1363:            private String writeArrayInfo(ArrayClassInfo info, String name) {
1364:                String arrayInfoName = name + "_ai";
1365:                classOut.println("STATIC const union {");
1366:                classOut.println("\tCVMArrayInfo ai;");
1367:                classOut.println("\tCVMConstantPool constantpool;");
1368:                classOut.println("} " + arrayInfoName + " = {{");
1369:                classOut
1370:                        .println("\t" + info.depth + ", " + info.baseType + ",");
1371:                classOut.println("\t(CVMClassBlock*)&"
1372:                        + cbName((CVMClass) info.baseClass.find().vmClass)
1373:                        + ",");
1374:                classOut.println("\t(CVMClassBlock*)&"
1375:                        + cbName((CVMClass) info.subarrayClass.find().vmClass));
1376:                classOut.println("}};");
1377:                return "&" + arrayInfoName + ".ai";
1378:            }
1379:
1380:            // return address of this constant pool.
1381:            private String writeConstants(ConstantPool cp, String name,
1382:                    boolean export) {
1383:                ConstantObject constants[] = cp.getConstants();
1384:                int clen = constants.length;
1385:                if ((clen == 0) || (clen == 1)) {
1386:                    return "0";
1387:                }
1388:
1389:                // Check if we need a type table.  When we write the class, we
1390:                // check for unquickened bytecodes.  If we find any, we mark
1391:                // the constant pool as needing a type table.  The check for
1392:                // unresolved entries should be redundant, because unreferenced
1393:                // entries should have been removed, and referenced entries
1394:                // should have an unquickened reference.
1395:
1396:                boolean doTypeTable = cp.needsTypeTable()
1397:                        || ClassClass.isPartiallyResolved(cp);
1398:
1399:                if (doTypeTable) {
1400:                    System.err.println("NEEDS TYPE TABLE");
1401:                }
1402:                if (doTypeTable && !classLoading) {
1403:                    // in future, do something more useful here.
1404:                    System.err.println(Localizer
1405:                            .getString("cwriter.no_class_loading"));
1406:                    // write the type table out anyway, in case
1407:                    // there is someone to look at it at runtime!
1408:                }
1409:                String typeTableName;
1410:                if (doTypeTable) {
1411:                    typeTableName = "CP_ADDR("
1412:                            + writeTypeTable(constants, name) + ")";
1413:                } else {
1414:                    typeTableName = "CP_ADDR(0)";
1415:                }
1416:                String constantPoolName = name + "_cp";
1417:                classOut.print(doTypeTable ? "" : "const ");
1418:                classOut.println("CVMAddr " + constantPoolName + "[" + (clen)
1419:                        + "] = {");
1420:                classOut.println("	(CVMAddr)" + typeTableName + ",");
1421:
1422:                if (export) {
1423:                    // Export in the global header for multiple components of
1424:                    // romjava files to find
1425:                    headerOut.print("extern ");
1426:                    headerOut.print(doTypeTable ? "" : "const ");
1427:                    headerOut.println("CVMAddr " + constantPoolName + "["
1428:                            + (clen) + "];");
1429:                }
1430:                for (int i = 1; i < clen; i += constants[i].nSlots) {
1431:                    classOut.print("    ");
1432:                    writeConstant(constants[i], classOut, "CP_");
1433:                    classOut.println(",");
1434:                }
1435:                classOut.println("};");
1436:                nconstants += clen;
1437:                return constantPoolName;
1438:            }
1439:
1440:            private void declareClassblock(CVMClass c, int innerClassCount) {
1441:                String myName = c.getNativeName();
1442:                String classblockFlavor = "struct CVMClassBlock"
1443:                        + innerClassCount;
1444:                if (!classblockSizes.get(innerClassCount)) {
1445:                    // need to declare a classblock-like struct with innerClassCount
1446:                    // elements in its CVMInnerClassInfo array
1447:                    if (innerClassCount < 1) {
1448:                        headerOut.println(classblockFlavor
1449:                                + " { CVMClassBlock classclass; };");
1450:                    } else {
1451:                        headerOut
1452:                                .println(classblockFlavor
1453:                                        + " { CVMClassBlock classclass; CVMUint32 innerClassesCount; CVMInnerClassInfo innerClasses[ "
1454:                                        + (innerClassCount) + "]; };");
1455:                    }
1456:                    classblockSizes.set(innerClassCount);
1457:                }
1458:                declare("const " + classblockFlavor + " " + myName
1459:                        + "_Classblock", classOut);
1460:            }
1461:
1462:            // helper for classBitMap
1463:            private static int GCbits(FieldInfo slottable[], int first, int last) {
1464:                int mapval = 0;
1465:                for (int i = first; i < last; i++) {
1466:                    switch (slottable[i].type.string.charAt(0)) {
1467:                    case 'L':
1468:                    case '[':
1469:                        // this is a reference.
1470:                        mapval |= 1 << (i - first);
1471:                    }
1472:                }
1473:                return mapval;
1474:            }
1475:
1476:            //
1477:            // compute the GC bit map for a class.
1478:            // if it is big, then write it out as well. In any case,
1479:            // return a string to use to initialize the gcMap field in the CVMClassBlock
1480:            //
1481:            private String classBitMap(CVMClass c) {
1482:                if (c.isArrayClass()) {
1483:                    // either an array of primitive or an array of objects.
1484:                    ArrayClassInfo ac = (ArrayClassInfo) (c.ci);
1485:                    if ((ac.depth == 1) && (ac.baseType != T_CLASS))
1486:                        return "0"; // contains no references
1487:                    else
1488:                        return "1"; // contains nothing but references.
1489:                }
1490:                ClassInfo ci = c.ci;
1491:                FieldInfo ft[] = ci.slottable;
1492:                if ((ft == null) || (ft.length == 0))
1493:                    return "0";
1494:                int nslots;
1495:                if ((nslots = ft.length) <= 30) {
1496:                    // easy case. Small object. Map can be represented in a word.
1497:                    return "0x"
1498:                            + Integer.toHexString(GCbits(ft, 0, nslots) << 2);
1499:                } else {
1500:                    // hard case.
1501:                    String myName = c.getNativeName() + "_gcBits";
1502:                    int nWords = (nslots + 31) / 32;
1503:                    classOut
1504:                            .print("STATIC const struct { CVMUint16 maplen; CVMUint32 map["
1505:                                    + nWords + "]; } ");
1506:                    classOut.print(myName);
1507:                    classOut.print(" = { ");
1508:                    classOut.print(nWords);
1509:                    classOut.print(",\n    {");
1510:                    for (int i = 0; i < nslots; i += 32) {
1511:                        classOut.print("0x"
1512:                                + Integer.toHexString(GCbits(ft, i, Math.min(
1513:                                        i + 32, nslots))));
1514:                        classOut.print(", ");
1515:                    }
1516:                    classOut.println("} };");
1517:                    return "(CVMAddr)(((char*)&" + myName
1518:                            + ")+ CVM_GCMAP_LONGGCMAP_FLAG)";
1519:                }
1520:            }
1521:
1522:            private void writeClassinfo(int classno, CVMClass c, int clinitIdx,
1523:                    int nStaticWords) {
1524:
1525:                if (c.hasStaticInitializer) {
1526:                    nClinits++;
1527:                }
1528:                String super Name = (c.ci.super ClassInfo == null) ? ("0")
1529:                        : ("&" + cbName((CVMClass) (c.ci.super ClassInfo.vmClass)));
1530:                String myStaticName = (c.nStaticWords == 0) ? ("0")
1531:                        : ("(CVMJavaVal32*)STATIC_STORE_ADDRESS(0)");
1532:                int innerClassCount = (c.ci.innerClassAttr == null) ? (0)
1533:                        : (c.ci.innerClassAttr.getInnerClassCount());
1534:                String runtimeFlags = (c.hasStaticInitializer || c.nStaticWords > 0) ? ("CVM_ROMCLASS_WCI_INIT")
1535:                        : ("CVM_ROMCLASS_INIT");
1536:                MethodInfo vtbl[] = c.ci.methodtable;
1537:                String methodTableName;
1538:                int methodTableCount;
1539:                String gcBits;
1540:
1541:                /*
1542:                 * Note: If this is a primitive class, the
1543:                 * typecode is stored in the methodTableCount field.
1544:                 * Since these things cannot be instantiated, they need
1545:                 * no virtual methods.
1546:                 */
1547:                if (c.isPrimitiveClass()) {
1548:                    methodTableCount = c.typecode();
1549:                    methodTableName = "0";
1550:                } else {
1551:                    // vtbl == null may occur for array classes! 
1552:                    methodTableCount = (vtbl == null) ? 0 : vtbl.length;
1553:                    if (methodTableCount > 0) {
1554:                        methodTableName = c.getNativeName() + "_mt";
1555:                    } else if (c.isArrayClass()) {
1556:                        methodTableName = "java_lang_Object_mt";
1557:                    } else { /* must be an interface */
1558:                        methodTableName = "0";
1559:                    }
1560:                }
1561:                // classBitMap may do output, so it needs
1562:                // to be called before declareClassblock!
1563:                gcBits = classBitMap(c);
1564:
1565:                declareClassblock(c, innerClassCount);
1566:
1567:                int classid = c.classid();
1568:                //System.out.println( c.ci.className+" => "+Integer.toHexString(classid) );
1569:
1570:                classOut.println(" = {\n    CVM_INIT_CLASSBLOCK( " + gcBits
1571:                        + ", " + "RAW_TYPEID(0, 0x"
1572:                        + Integer.toHexString(classid) + "), \""
1573:                        + c.ci.className + "\",");
1574:                classOut.println("    " + super Name + ",");
1575:                classOut.println("    " + constantPoolName + ", ");
1576:                classOut.println("    " + interfaceTableName + ",");
1577:                classOut.println("    " + methodArrayName + ",");
1578:                classOut.println("    " + fieldTableName + ", " + myStaticName
1579:                        + ",");
1580:                classOut.println("    " + constantPoolSize + ", "
1581:                        + methodTableSize + ", " + fieldTableSize + ", "
1582:                        + methodTableCount + ", " + c.CVMflags() + ", "
1583:                        + runtimeFlags + ", " + nStaticWords + " + "
1584:                        + clinitIdx + ", OBJ_SIZE(" + c.instanceSize() + "), ");
1585:                classOut.println("    (CVMClassICell*)(&CVM_classICell["
1586:                        + classno + "]), ");
1587:                /* The slots for clinitEE is appended to 'staticStoreName'. */
1588:                /* 
1589:                 * Moved global variables to CVMROMGlobals
1590:                 */
1591:                classOut.println("    (CVMExecEnv**)&CVMROMGlobals."
1592:                        + staticStoreName + "[" + nStaticWords + " + "
1593:                        + clinitIdx + "],");
1594:                classOut.println("    " + checkedExceptionName + ", ");
1595:                if (classDebug && c.ci.sourceFileAttr != null) {
1596:                    classOut.println("    \"" + c.ci.sourceFileAttr.sourceName
1597:                            + "\", ");
1598:                } else {
1599:                    classOut.println("    0, ");
1600:                }
1601:
1602:                /* write out the methodTablePtr. */
1603:                classOut.println("    " + methodTableName + ",");
1604:
1605:                /* write out the ClassLoader and ProtectionDomain */
1606:                int id = c.ci.loader.getID();
1607:                if (id != 0) {
1608:                    int clIDOff = 1; // first cl ID (boot == 0)
1609:                    int off = clRefOff + (id - clIDOff) * 2;
1610:                    classOut.println("    (CVMClassLoaderICell *)"
1611:                            + "STATIC_STORE_ADDRESS(" + off + "), "
1612:                            + "(CVMObjectICell *)" + "STATIC_STORE_ADDRESS("
1613:                            + (off + 1) + "),");
1614:                } else {
1615:                    classOut.println("    0, 0,");
1616:                }
1617:
1618:                /* write out the InnerClassesInfo */
1619:                if (c.ci.innerClassAttr != null) {
1620:                    classOut.println("    &" + c.getNativeName()
1621:                            + "_Classblock.innerClassesCount),");
1622:                    writeInnerClasses(c);
1623:                } else {
1624:                    classOut.println("    0)");
1625:                }
1626:
1627:                classOut.println("};");
1628:            }
1629:
1630:            void writeMethodTable(CVMClass c) {
1631:                MethodInfo vtbl[] = c.ci.methodtable;
1632:                int vtblSize;
1633:
1634:                /*
1635:                 * Note: If this is a primitive class, the
1636:                 * typecode is stored in the methodTableCount field.
1637:                 * Since these things cannot be instantiated, they need
1638:                 * no virtual methods.
1639:                 */
1640:                if (c.isPrimitiveClass()) {
1641:                    return;
1642:                } else {
1643:                    // vtbl == null may occur for array classes! 
1644:                    vtblSize = (vtbl == null) ? 0 : vtbl.length;
1645:                }
1646:
1647:                if (vtblSize > 0) {
1648:                    /* write out the methodtable. */
1649:                    String methodTableName = c.getNativeName() + "_mt" + "["
1650:                            + vtblSize + "]";
1651:                    if (c.ci.super Class == null) { // is it java/lang/Object
1652:                        // java/lang/Object needs an extern methodTable declaration.
1653:                        /* Added another const (for the pointer, which is also
1654:                         * const here, not just the data) 
1655:                         */
1656:                        declare("const CVMMethodBlock* const "
1657:                                + methodTableName, classOut);
1658:                    } else {
1659:                        /* 
1660:                         * Added another const (for the pointer, which is also const here, not just the data)
1661:                         */
1662:                        classOut.print("STATIC const CVMMethodBlock* const "
1663:                                + methodTableName);
1664:                    }
1665:                    classOut.println(" = {");
1666:                    for (int i = 0; i < vtblSize; i++) {
1667:                        classOut.println("    (CVMMethodBlock*)"
1668:                                + methodBlockAddress(vtbl[i]) + ",");
1669:                    }
1670:                    classOut.println("};\n");
1671:                }
1672:            }
1673:
1674:            /* (These two belong directly in the CCodeWriter) */
1675:
1676:            private void writeIntegerValue(int v, CCodeWriter out) {
1677:                // little things make gcc happy.
1678:                if (v == 0x80000000)
1679:                    out.print("(CVMInt32)0x80000000");
1680:                else
1681:                    out.print(v);
1682:            }
1683:
1684:            private void writeLongValue(String tag, int highval, int lowval,
1685:                    CCodeWriter out) {
1686:                out.print(tag);
1687:                out.write('(');
1688:                writeIntegerValue(highval, out);
1689:                out.print(", ");
1690:                writeIntegerValue(lowval, out);
1691:                out.write(')');
1692:            }
1693:
1694:            /* 
1695:             * Added prefix argument to differ between writing entries to the
1696:             * constant pool (where prefix="CP_") and the rest (where prefix
1697:             * is empty). Additionally we use the INTEGER/LONG/... macros now
1698:             * everywhere in this function to indicate, what type we are writing
1699:             * (may be hard to spot otherwise).
1700:             */
1701:            private void writeConstant(ConstantObject value, CCodeWriter out,
1702:                    String prefix) {
1703:                switch (value.tag) {
1704:                case Const.CONSTANT_INTEGER:
1705:                case Const.CONSTANT_FLOAT:
1706:                    /* 
1707:                     * add INTEGER macro like the one for LONG and DOUBLE
1708:                     * to have the possibility to change the representation
1709:                     * platform dependent
1710:                     */
1711:                    /* 
1712:                     * Add prefix to macro to get correct version.
1713:                     */
1714:                    out.print(prefix + "INTEGER(");
1715:                    writeIntegerValue(((SingleValueConstant) value).value, out);
1716:                    out.print(")");
1717:                    break;
1718:                case Const.CONSTANT_UTF8:
1719:                    out.print("(CVMInt32)");
1720:                    out.write('"');
1721:                    out.print(Util
1722:                            .unicodeToUTF(((UnicodeConstant) value).string));
1723:                    out.write('"');
1724:                    // also, not sharing here at all.
1725:                    break;
1726:                case Const.CONSTANT_STRING:
1727:                    /* 
1728:                     * Moved global variables to CVMROMGlobals
1729:                     */
1730:                    /* CVM_BIGTYPEID: RS, 10/08/02:
1731:                     * Use ADDR() macro to print out address.
1732:                     */
1733:                    out.print(prefix + "ADDR(&CVMROMGlobals." + stringArrayName
1734:                            + "[");
1735:                    if (((StringConstant) value).unicodeIndex == -1) {
1736:                        // Uninitialized, very bad
1737:                        throw new InternalError(
1738:                                "Uninitialized string constant " + value);
1739:                    } else {
1740:                        out.print(((StringConstant) value).unicodeIndex);
1741:                    }
1742:
1743:                    out.print("])");
1744:                    break;
1745:                case Const.CONSTANT_LONG: {
1746:                    DoubleValueConstant dval = (DoubleValueConstant) value;
1747:                    /*
1748:                     * Add prefix to macro to get correct version.
1749:                     */
1750:                    writeLongValue("LONG", dval.highVal, dval.lowVal, out);
1751:                }
1752:                    break;
1753:                case Const.CONSTANT_DOUBLE: {
1754:                    DoubleValueConstant dval = (DoubleValueConstant) value;
1755:                    /*
1756:                     * Add prefix to macro to get correct version.
1757:                     */
1758:                    writeLongValue("DOUBLE", dval.highVal, dval.lowVal, out);
1759:                }
1760:                    break;
1761:                case Const.CONSTANT_CLASS:
1762:                    if (value.isResolved()) {
1763:                        /* 
1764:                         * Use ADDR() macro to print out address.
1765:                         */
1766:                        out.print(prefix
1767:                                + "ADDR(&"
1768:                                + cbName((CVMClass) (((ClassConstant) value)
1769:                                        .find().vmClass)) + ")");
1770:                    } else {
1771:                        int classid = CVMDataType
1772:                                .lookupClassname(getUTF(((ClassConstant) value).name));
1773:                        /*
1774:                         * Use TYPEID() macro to create typeid from type part.
1775:                         */
1776:                        out.print(prefix + "TYPEID(0, 0x"
1777:                                + Integer.toHexString(classid) + ")");
1778:                    }
1779:                    break;
1780:                case Const.CONSTANT_METHOD:
1781:                case Const.CONSTANT_INTERFACEMETHOD:
1782:                    if (value.isResolved()) {
1783:                        /*
1784:                         * Use ADDR() macro to print out address.
1785:                         */
1786:                        out.print(prefix + "ADDR(");
1787:                        out.print(methodBlockAddress(((MethodConstant) value)
1788:                                .find())
1789:                                + ")");
1790:                    } else {
1791:                        FMIrefConstant ref = (FMIrefConstant) value;
1792:                        /* 
1793:                         * Use MEMBER_REF() macro to create entry for parts.
1794:                         * This is a pair of 16-bit indices into the cp.
1795:                         * They reference a Class constant and a NameAndType
1796:                         * constant.
1797:                         * It is not a typeId.
1798:                         */
1799:                        out
1800:                                .print(prefix
1801:                                        + "MEMBER_REF(0x"
1802:                                        + Integer.toHexString(ref.clas
1803:                                                .getIndex())
1804:                                        + ", 0x"
1805:                                        + Integer.toHexString(ref.sig
1806:                                                .getIndex()) + ")");
1807:                    }
1808:                    break;
1809:                case Const.CONSTANT_FIELD:
1810:                    if (value.isResolved()) {
1811:                        FieldInfo ftarget = ((FieldConstant) value).find();
1812:                        ClassInfo ctarget = ftarget.parent;
1813:                        // ROMized code always use checkinit version of opcodes
1814:                        // to access fields including static fields.
1815:                        /*
1816:                         * Add prefix to macro to get correct version.
1817:                         */
1818:                        out.print(prefix + "ADDR(" + fieldBlockAddress(ftarget)
1819:                                + ")");
1820:                    } else {
1821:                        FMIrefConstant ref = (FMIrefConstant) value;
1822:                        /* 
1823:                         * Use MEMBER_REF() macro to create entry for parts.
1824:                         * This is a pair of 16-bit indices into the cp.
1825:                         * They reference a Class constant and a NameAndType
1826:                         * constant.
1827:                         * It is not a typeId.
1828:                         */
1829:                        out
1830:                                .print(prefix
1831:                                        + "MEMBER_REF(0x"
1832:                                        + Integer.toHexString(ref.clas
1833:                                                .getIndex())
1834:                                        + ", 0x"
1835:                                        + Integer.toHexString(ref.sig
1836:                                                .getIndex()) + ")");
1837:                    }
1838:                    break;
1839:                case CONSTANT_NAMEANDTYPE:
1840:                    NameAndTypeConstant ntcon = (NameAndTypeConstant) value;
1841:                    int nameid = CVMMemberNameEntry
1842:                            .lookupEnter(getUTF(ntcon.name));
1843:                    String sigString = getUTF(ntcon.type);
1844:                    int typeid = (sigString.charAt(0) == SIGC_METHOD) ? (CVMMethodType
1845:                            .parseSignature(sigString).entryNo)
1846:                            : (CVMDataType.parseSignature(sigString));
1847:                    /* 
1848:                     * Use TYPEID() macro to create typeid from parts.
1849:                     */
1850:                    out.print("TYPEID(0x" + Integer.toHexString(nameid)
1851:                            + ", 0x" + Integer.toHexString(typeid) + ")");
1852:                    break;
1853:                }
1854:            }
1855:
1856:            private int clRefOff;
1857:
1858:            /*
1859:             * Merge the static store for all classes into one area.
1860:             * Sort static cells, refs first, and assign offsets.
1861:             * Write the resulting master data glob and arrange for
1862:             * it to be copied to writable at startup.
1863:             */
1864:            private int writeStaticStore(ClassClass cvec[]) {
1865:                int nclass = cvec.length;
1866:                int nStaticWords = 1; // 1 header word assumed
1867:                int nRef = 0;
1868:                /* The number of necessary slots for clinitEE + 1.
1869:                 * Index of a class that doesn't have <clinit> is always 0.
1870:                 * The 0th entry is reserved for it. */
1871:                int maxClinitIdx = 1;
1872:
1873:                int maxClIdx = 0;
1874:
1875:                /*
1876:                 * Count all statics.
1877:                 * Count refs, and count number of words.
1878:                 */
1879:                for (int cno = 0; cno < nclass; cno++) {
1880:                    CVMClass c = (CVMClass) (cvec[cno]);
1881:                    c.orderStatics();
1882:                    nRef += c.nStaticRef;
1883:                    nStaticWords += c.nStaticWords;
1884:                    /* Count the number of necessary slots for clinitEE. */
1885:                    if (c.hasStaticInitializer) {
1886:                        maxClinitIdx++;
1887:                    }
1888:                }
1889:
1890:                int ncl = components.ClassTable.getNumClassLoaders();
1891:                nRef += ncl * 2;
1892:                nStaticWords += ncl * 2;
1893:
1894:                /*
1895:                 * Assign offsets and at the same time
1896:                 * record any initial values.
1897:                 * write it later.
1898:                 */
1899:                int refOff = 1;
1900:                int scalarOff = refOff + nRef;
1901:
1902:                ConstantObject staticInitialValue[] = new ConstantObject[nStaticWords];
1903:                short staticInitialSize[] = new short[nStaticWords];
1904:
1905:                clRefOff = refOff;
1906:                for (int i = 0; i < ncl; ++i) {
1907:                    staticInitialValue[refOff] = null;
1908:                    staticInitialSize[refOff] = 1;
1909:                    ++refOff;
1910:                    staticInitialValue[refOff] = null;
1911:                    staticInitialSize[refOff] = 1;
1912:                    ++refOff;
1913:                }
1914:
1915:                for (int cno = 0; cno < nclass; cno++) {
1916:                    CVMClass c = (CVMClass) (cvec[cno]);
1917:                    FieldInfo f[] = c.statics;
1918:                    if ((f == null) || (f.length == 0))
1919:                        continue; // this class has none
1920:                    int nFields = f.length;
1921:                    for (int i = 0; i < nFields; i++) {
1922:                        FieldInfo fld = f[i];
1923:                        short nslots = (short) (fld.nSlots);
1924:                        char toptype = fld.type.string.charAt(0);
1925:                        if ((toptype == 'L') || (toptype == '[')) {
1926:                            fld.instanceOffset = refOff;
1927:                            staticInitialValue[refOff] = fld.value;
1928:                            staticInitialSize[refOff] = 1;
1929:                            refOff += 1;
1930:                        } else {
1931:                            fld.instanceOffset = scalarOff;
1932:                            staticInitialValue[scalarOff] = fld.value;
1933:                            staticInitialSize[scalarOff] = nslots;
1934:                            scalarOff += nslots;
1935:                        }
1936:                    }
1937:                }
1938:
1939:                /*
1940:                 * Allocate writable space for the static store.
1941:                 * Start writing the static storage header.
1942:                 * Remember that the first word is the number of refs.
1943:                 * And many of those refs get initialized to zero.
1944:                 * A static final String constant gets initialized with a pointer.
1945:                 * 
1946:                 * The buffer holds static field slots for the ROMized classes and 
1947:                 * cliniEE (that includes runtime flags) slots for ROMized classes.
1948:                 * The slot allocation looks like this:
1949:                 *
1950:                 *   CVM_StaticDataMaster[]
1951:                 *   +---+---+-- --+---+-- --+---+---+---+-- --+---+
1952:                 *   | 0 | 1 | ... | i | ... |n-1|n+0|n+1| ... |n+m|
1953:                 *   +-^-+-^-+-- --+-^-+-- --+-^-+-^-+-^-+-- --+-^+
1954:                 *     |   |         |         |   |   |         |
1955:                 *     |   |         |         |   |   |   the last clinitEE slot for
1956:                 *     |   |         |         |   |   |   ROMized class w/<clinit>
1957:                 *     |   |    the last       |   |   |
1958:                 *     |   |    static ref     |   | the 1st clinitEE slot for
1959:                 *     |   |                   |   | ROMized class w/<clinit>
1960:                 *     | the 1st               |   |
1961:                 *     | static ref            | shared clinitEE slot
1962:                 *     |                       | for ROMized classes w/o <clinit>
1963:                 *   the number of             |
1964:                 *   static refs (== i)   the end of static fields
1965:                 *
1966:                 *   where:
1967:                 *     i := the number of static reference slots
1968:                 *     n := the number of static field slots (including the 0th slot)
1969:                 *     m := the number of clinitEE slots
1970:                 */
1971:                /* 
1972:                 * Moved global variables to CVMROMGlobals
1973:                 */
1974:                globalHeaderOut.println("    CVMAddr " + staticStoreName
1975:                        + "[CVM_STATIC_OFFSET(" + nStaticWords + " + "
1976:                        + maxClinitIdx + ")];");
1977:                auxOut.println("const CVMUint32 " + numStaticStoreName + " = "
1978:                        + nStaticWords + " + " + maxClinitIdx + ";");
1979:                auxOut.print("const CVMAddr " + masterStaticStoreName
1980:                        + "[] = {\n    ");
1981:                auxOut.print(nRef); // the initial count word.
1982:                auxOut.print(",");
1983:                //System.out.println(nRef + " reference statics, total words "+nStaticWords );
1984:
1985:                short nslots = 1;
1986:                int nConstPerLine = 1; // the initial count word.
1987:                for (int i = 1; i < nStaticWords; i += nslots) {
1988:                    ConstantObject v = staticInitialValue[i];
1989:                    nslots = staticInitialSize[i];
1990:                    if (v == null) {
1991:                        /*
1992:                         * Use INTEGER() macro here for consistency.
1993:                         */
1994:                        auxOut.print("INTEGER(0)");
1995:                        if (nslots == 2)
1996:                            /*
1997:                             * Use INTEGER() macro here for consistency.
1998:                             */
1999:                            auxOut.print(", INTEGER(0)");
2000:                    } else {
2001:                        /*
2002:                         * Use normal macros (not the CP_-variants) for the constants.
2003:                         */
2004:                        writeConstant(v, auxOut, "");
2005:                    }
2006:                    auxOut.print(", ");
2007:                    nConstPerLine += nslots;
2008:                    if (nConstPerLine >= 8) {
2009:                        auxOut.print("\n    ");
2010:                        nConstPerLine = 0;
2011:                    }
2012:                }
2013:
2014:                /* Append slots for clinitEE after static fields */
2015:                auxOut.print("\n");
2016:                auxOut.print("    /* clinitEEs */\n");
2017:                auxOut.print("    CVM_CLINITEE_CLASS_INIT_FLAG");
2018:                for (int i = 1; i < maxClinitIdx; i++) {
2019:                    auxOut.print(", ");
2020:                    if (i % 8 == 0) {
2021:                        auxOut.print("\n    ");
2022:                    }
2023:                    /*
2024:                     * Use INTEGER() macro here for consistency.
2025:                     */
2026:                    auxOut.print("INTEGER(0)");
2027:                }
2028:                auxOut.println("\n};");
2029:                /* 
2030:                 * Moved globals to CVMROMGlobals.
2031:                 */
2032:                initInfo.addInfo("&" + masterStaticStoreName, "CVMROMGlobals."
2033:                        + staticStoreName, "(" + nStaticWords + " + "
2034:                        + maxClinitIdx + ")" + "*sizeof(CVMAddr)");
2035:
2036:                return nStaticWords;
2037:            }
2038:
2039:            /*
2040:             * typedef struct {
2041:             *     char *hash;			 * the string for this entry * 
2042:             *     unsigned long info;		 * high bit set if malloc'ed
2043:             * 				 * low 31 bits are the low 31 bits of hash * 
2044:             * #define MALLOCED_FLAG (1u << 31)
2045:             * #define HASHBIT_MASK (MALLOCED_FLAG - 1)
2046:             * } StrIDhashSlot;
2047:             *
2048:             * typedef struct StrIDhash {
2049:             *     int size;			* number of entries *
2050:             *     hash_fn hash;		* hash function for this table *
2051:             *     struct StrIDhash *next;	* next bucket *
2052:             *     short used;			* number of full entries *
2053:             *     short baseid;		* ID for item in slot[0] *
2054:             *     void **params;		* param table, if needed *
2055:             *     StrIDhashSlot slot[1];	* expanded to be number of slots *
2056:             * } StrIDhash;
2057:             */
2058:
2059:            private String idTypeDecl[] = { "extern void default_hash();",
2060:                    "typedef struct {", "    const char *hash;",
2061:                    "    unsigned long info;", "} StrIDhashSlot;",
2062:                    "#define STR_ID_HASH(n)  struct { \\", "    int size; \\",
2063:                    "    void (*hash)(); \\", "    void *next; \\",
2064:                    "    short used; \\", "    short baseid; \\",
2065:                    "    HString **params; \\",
2066:                    "    StrIDhashSlot slot[ n ]; \\", "} " };
2067:
2068:            /*
2069:             * These are macros to encapsulate some of the messiness
2070:             * of data definitions. They are, perhaps, compiler-specific.
2071:             */
2072:            private static String stdHeader[] = {
2073:                    "#define IN_ROMJAVA 1",
2074:                    "#include \"javavm/include/defs.h\"",
2075:                    "#include \"javavm/include/objects.h\"",
2076:                    "#include \"javavm/include/classes.h\"",
2077:                    "#include \"javavm/include/interpreter.h\"",
2078:                    "#include \"javavm/include/jni_impl.h\"",
2079:                    "#include \"javavm/include/typeid.h\"",
2080:                    "#include \"javavm/include/typeid_impl.h\"",
2081:                    "#include \"javavm/include/string_impl.h\"",
2082:                    "#include \"javavm/include/preloader_impl.h\"",
2083:                    "#include \"javavm/include/porting/endianness.h\"",
2084:                    "#ifdef CVM_JIT",
2085:                    "#include \"javavm/include/porting/jit/ccm.h\"",
2086:                    "#endif",
2087:                    /* 
2088:                     * add possibility to change the INTEGER
2089:                     * representation per platform
2090:                     *
2091:                     * Linux s390x:
2092:                     * Loading an integer/float constant failed on 64 bit because
2093:                     * the integer representation in the constant pool array
2094:                     * includes the bits for the 4 byte int/float
2095:                     * but is casted to a 8 byte value for 64 bit platforms (CVMAddr)
2096:                     * which meens that the memory representation is changed.
2097:                     * Therefore make sure the int/float representation looks like
2098:                     * byte 0         4         8
2099:                     *      |- int   -|-  pad  -|
2100:                     * on 64 bit platforms with big endian.
2101:                     */
2102:                    "/* CVM_BIGTYPEID: RS, 10/14/02:",
2103:                    " * Added macros to put different data types safely into their designated",
2104:                    " * structures. Unprefixed macro put the types into unions of the same size",
2105:                    " * as CVMAddr and macros prefixed with CP_ are used to put the specific",
2106:                    " * types into the constant pool.",
2107:                    " *",
2108:                    " * INTEGER(i)                 : Use this, if you want to write an integer",
2109:                    " * LONG(high, low)            : Use this, if you want to write a long",
2110:                    " *                              value consisting of the given high and low parts.",
2111:                    " * DOUBLE(high, low)          : Use this, if you want to write a double",
2112:                    " *                              value consisting of the given high and low parts.",
2113:                    " * ADDR(addr)                 : Use this, if you want to write an address.",
2114:                    " * TYPEID(namePart, typePart) : Use this, if you want to write a typeid consisting",
2115:                    " *                              of the given name and type parts.",
2116:                    " *",
2117:                    " * The following just return the typeids and their parts as their native types:",
2118:                    " *",
2119:                    " * RAW_TYPEID_NAME_PART(namePart) : Use this, if you want to write the name part of a typeid.",
2120:                    " * RAW_TYPEID_TYPE_PART(typePart) : Use this, if you want to write the type part of a typeid.",
2121:                    " * RAW_TYPEID(namePart, typePart) : Use this, if you want to write a typeid consisting",
2122:                    " *                                  of the given name and type parts.",
2123:                    " */",
2124:                    "",
2125:                    "#define RAW_TYPEID_NAME_PART(namePart) \\",
2126:                    "        ((CVMTypeIDNamePart) (namePart))",
2127:                    "",
2128:                    "#define RAW_TYPEID_TYPE_PART(typePart) \\",
2129:                    "        ((CVMTypeIDTypePart) (typePart))",
2130:                    "",
2131:                    "#define RAW_TYPEID(namePart, typePart) \\",
2132:                    "        CVMtypeidCreateTypeIDFromParts(RAW_TYPEID_NAME_PART((namePart)), RAW_TYPEID_TYPE_PART((typePart)))",
2133:                    "",
2134:                    "",
2135:                    "#if !defined(CVM_64)",
2136:                    "#    define TYPEID(namePart, typePart) RAW_TYPEID((namePart), (typePart))",
2137:                    "#else",
2138:                    "#    define TYPEID(namePart, typePart) INTEGER(RAW_TYPEID((namePart), (typePart)))",
2139:                    "#endif",
2140:                    "",
2141:                    "",
2142:                    "#define ADDR(addr) ((CVMAddr) (addr))",
2143:                    "",
2144:                    "",
2145:                    "#ifdef CVM_64",
2146:                    "",
2147:                    "#    define LONG(high, low) (((CVMAddr) (high) << 32) | ((CVMAddr) (low) & 0x0ffffffff)), 0",
2148:                    "#    define DOUBLE(high, low) LONG((high), (low))",
2149:                    "",
2150:                    "#    if (CVM_ENDIANNESS == CVM_BIG_ENDIAN)",
2151:                    "#        define INTEGER(i) (((CVMAddr) (i)) << 32)",
2152:                    "#    else",
2153:                    "#        define INTEGER(i) ((CVMAddr) (i))",
2154:                    "#    endif",
2155:                    "",
2156:                    "#else /* CVM_64 */",
2157:                    "",
2158:                    "#    define INTEGER(i) ADDR(i)",
2159:                    "",
2160:                    "#    if (CVM_ENDIANNESS == CVM_BIG_ENDIAN)",
2161:                    "#        define LONG(high, low) ADDR(high), ADDR(low)",
2162:                    "#    else",
2163:                    "#        define LONG(high, low) ADDR(low), ADDR(high)",
2164:                    "#    endif",
2165:                    "",
2166:                    "#    if (CVM_DOUBLE_ENDIANNESS == CVM_BIG_ENDIAN)",
2167:                    "#        define DOUBLE(high, low) ADDR(high), ADDR(low)",
2168:                    "#    else",
2169:                    "#        define DOUBLE(high, low) ADDR(low), ADDR(high)",
2170:                    "#    endif",
2171:                    "",
2172:                    "#endif /* CVM_64 */",
2173:                    "",
2174:                    "",
2175:                    "#define CP_ADDR(addr) ADDR((addr))",
2176:                    "#define CP_INTEGER(i) INTEGER((i))",
2177:                    "#define CP_LONG(high, low) LONG((high), (low))",
2178:                    "#define CP_DOUBLE(high, low) DOUBLE((high), (low))",
2179:                    "#define CP_TYPEID(namePart, typePart) TYPEID((namePart), (typePart))",
2180:                    "#if (CVM_ENDIANNESS == CVM_BIG_ENDIAN)",
2181:                    "#    define CP_MEMBER_REF(classPart,typePart) INTEGER((((classPart)<<16)+(typePart)))",
2182:                    "#else",
2183:                    "#    define CP_MEMBER_REF(classPart,typePart) INTEGER((((typePart)<<16)+(classPart)))",
2184:                    "#endif",
2185:                    "",
2186:                    "",
2187:
2188:                    "#ifdef _MSC_VER",
2189:                    "#define STATIC /* static */",
2190:                    "#else",
2191:                    "#define STATIC static",
2192:                    "#endif",
2193:
2194:                    "#define SCALARTYPE_NO(n) (n)",
2195:                    //"#define MSIG_NO(n) ((struct methodTypeTableEntry*)&CVMMethodSigTable.typeSig[n])",
2196:                    "#define NAME_NO(n) (n)",
2197:                    "#define SIG_DETAIL_NO(n) (&msig_details[n])",
2198:                    /* 
2199:                     * Moved globals to CVMROMGlobals.
2200:                     */
2201:                    "#define STATIC_STORE_ADDRESS(n) (&CVMROMGlobals."
2202:                            + staticStoreName + "[CVM_STATIC_OFFSET(n)])",
2203:                    "",
2204:                    /* 
2205:                     * Moved globals to CVMROMGlobals.
2206:                     */
2207:                    /*
2208:                    "extern CVMInt32 "+staticStoreName+"[];",
2209:                     */
2210:                    /* 
2211:                     * Added another const (for the pointer, which is also const
2212:                     * here, not just the data) 
2213:                     */
2214:                    "extern const CVMMethodBlock* const java_lang_Object_mt[];",
2215:                    "",
2216:
2217:            };
2218:
2219:            /* this is target-dependent and belongs in a header file... */
2220:            private static String targetHeader[] = {};
2221:
2222:            /* 
2223:             * Added header file for globals
2224:             */
2225:            private void writeGlobalHeaderPrologue(BufferedPrintStream o) {
2226:                o
2227:                        .println("/* This file contains all global and static variables that were");
2228:                o.println(" * originally in the generated files.");
2229:                o.println(" */");
2230:                o.println("struct CVMROMGlobalState");
2231:                o.println("{");
2232:            }
2233:
2234:            private void writeGlobalHeaderEpilogue(BufferedPrintStream o) {
2235:                o.println("};");
2236:                o.println("");
2237:                o.println("extern struct CVMROMGlobalState CVMROMGlobals;");
2238:            }
2239:
2240:            private void writeHeaderPrologue(BufferedPrintStream o) {
2241:
2242:                for (int i = 0; i < targetHeader.length; i++) {
2243:                    o.println(targetHeader[i]);
2244:                }
2245:                for (int i = 0; i < stdHeader.length; i++) {
2246:                    o.println(stdHeader[i]);
2247:                }
2248:
2249:                o.println("");
2250:            }
2251:
2252:            /* 
2253:             * Moved global variables to CVMROMGlobals
2254:             */
2255:            private void writeHeaderEpilogue(BufferedPrintStream o) {
2256:                o.println("");
2257:                o.println("/* Moved global variables to CVMROMGlobals");
2258:                o.println(" */");
2259:                o.println("");
2260:                o.println("#include \"" + globalHeaderFileName + "\"");
2261:            }
2262:
2263:            private void writePrologue(BufferedPrintStream o) {
2264:                if (headerFileName != null) {
2265:                    o.println("#include \"" + headerFileName + "\"");
2266:                }
2267:            }
2268:
2269:            private static String cbName(CVMClass c) {
2270:                return c.getNativeName() + "_Classblock.classclass";
2271:            }
2272:
2273:            private void writeClass(int classno, CVMClass c, int clinitIdx,
2274:                    int nStaticWords) {
2275:
2276:                classOut.println("\n/* ******** Class " + c.getNativeName()
2277:                        + " ******** */");
2278:
2279:                classBlockName = cbName(c);
2280:
2281:                writeMethods(c);
2282:                // writeInterfaces(c);
2283:                interfaceTableName = (c.inf.iv.length == 0) ? "0" : ("&"
2284:                        + c.inf.name + ".interfaces");
2285:
2286:                writeFields(c);
2287:
2288:                if (c.isArrayClass()) {
2289:                    ArrayClassInfo info = (ArrayClassInfo) c.ci;
2290:                    constantPoolName = writeArrayInfo(info, c.getNativeName());
2291:                    constantPoolSize = 0;
2292:                } else {
2293:                    if (doShared) {
2294:                        constantPoolName = sharedConstantPoolName + "_cp";
2295:                        constantPoolSize = sharedConstantPoolSize;
2296:                    } else {
2297:                        ConstantPool cpool = c.ci.getConstantPool();
2298:                        constantPoolName = writeConstants(cpool, c
2299:                                .getNativeName(), false);
2300:                        constantPoolSize = cpool.getLength();
2301:                    }
2302:                }
2303:
2304:                writeMethodTable(c);
2305:                writeClassinfo(classno, c, clinitIdx, nStaticWords);
2306:
2307:            }
2308:
2309:            private void processStrings(ConstantPool cp) {
2310:                int n = cp.getLength();
2311:                for (int i = 1; i < n;) {
2312:                    ConstantObject obj = cp.elementAt(i);
2313:                    if (obj instanceof  StringConstant) {
2314:                        stringTable.intern((StringConstant) obj);
2315:                    }
2316:                    i += obj.nSlots;
2317:                }
2318:            }
2319:
2320:            private void classProcessStrings(ClassInfo c, boolean doShared) {
2321:                FieldInfo f[] = c.fields;
2322:                int fieldCount = (f == null) ? 0 : f.length;
2323:                if (!doShared) {
2324:                    processStrings(c.getConstantPool());
2325:                }
2326:                //
2327:                // make sure that strings appearing ONLY as static final
2328:                // initializer values get processed, too.
2329:                //
2330:                for (int i = 0; i < fieldCount; i++) {
2331:                    FieldInfo fi = f[i];
2332:                    if (fi.isStaticMember()
2333:                            && fi.value instanceof  StringConstant) {
2334:                        stringTable.intern((StringConstant) (fi.value));
2335:                    }
2336:                }
2337:            }
2338:
2339:            private void instantiateAllStrings() {
2340:                njavastrings = stringTable.writeStrings(auxOut,
2341:                        masterStringArrayName);
2342:                globalHeaderOut.println("    struct java_lang_String "
2343:                        + stringArrayName + "[" + njavastrings + "];");
2344:                auxOut.println("const int CVM_nROMStrings = " + njavastrings
2345:                        + ";");
2346:                auxOut
2347:                        .println("CVMArrayOfChar* const CVM_ROMStringsMasterDataPtr = (CVMArrayOfChar* const)&CVM_ROMStringsMaster_data.hdr;");
2348:
2349:                /* 
2350:                 * Moved global variables to CVMROMGlobals
2351:                 * That makes it necessary to pass the global header out file into writeStringInternTable.
2352:                 */
2353:                stringTable.writeStringInternTable(auxOut, globalHeaderOut,
2354:                        "CVMInternTable", stringArrayName);
2355:            }
2356:
2357:            /*
2358:             * Our representation of method types has four variations:
2359:             *	0: inline form, inline details;
2360:             *  1: inline form, outboard details;
2361:             *  2: outboard form, inline details (rare);
2362:             *  3: outboard form, outboard details, too.
2363:             * For our own convenience, we are going to segregate them
2364:             * by type. This affects the indexing scheme, so we must
2365:             * assign that, too, after the sort.
2366:             */
2367:            private static int variety(CVMMethodType mt) {
2368:                int v = 0;
2369:                if (mt.form.nSyllables > CVMSigForm.SYLLABLESPERDATUM)
2370:                    v += 2;
2371:                if (mt.nDetails > 2)
2372:                    v += 1;
2373:                return v;
2374:            }
2375:
2376:            private void enumerateMethodTypes() {
2377:                methodTypes = new CVMMethodType[4];
2378:                nMethodTypes = new int[4];
2379:                Enumeration e = CVMMethodType.methodTypes.elements();
2380:                while (e.hasMoreElements()) {
2381:                    CVMMethodType mt = (CVMMethodType) (e.nextElement());
2382:                    int v = variety(mt);
2383:                    mt.listNext = methodTypes[v];
2384:                    methodTypes[v] = mt;
2385:                    nMethodTypes[v] += 1;
2386:                }
2387:                int curTypeNo = 0;
2388:                for (int i = 0; i < 4; i++) {
2389:                    for (CVMMethodType mt = methodTypes[i]; mt != null; mt = mt.listNext) {
2390:                        mt.entryNo = curTypeNo++;
2391:                    }
2392:                }
2393:                totalMethodTypes = curTypeNo;
2394:            }
2395:
2396:            /*
2397:             * The CVM type structures are built up as a side effect of
2398:             * turning signatures and names into 16-bit cookies while writing out
2399:             * other structures. Thus they must be written AFTER all the entries are
2400:             * computed. Fortunately there will be no forward-references to them,
2401:             * as all references are by index values, not addresses.
2402:             */
2403:            private void writeCVMNameAndTypeTables() {
2404:                writeCVMpkgHeader();
2405:                writeCVMDataTypeTable();
2406:                writeCVMpkg();
2407:                writeCVMMethodTypeTable();
2408:                writeCVMMemberNameTable();
2409:            }
2410:
2411:            /*
2412:             * The value-type table is one of the larger type structures, as it also
2413:             * holds class names. It has variant records. It contains an internal linked
2414:             * list for lookup-by-name. It has reference counts, but we will set these
2415:             * to the magic maximum value so that this can be READONLY.
2416:             */
2417:            private void writeCVMDataTypeTable() {
2418:                Vector allDataTypes = CVMDataType.dataTypes;
2419:                int nData = allDataTypes.size();
2420:                /*
2421:                 * May need to do an iteration through to determine the layout, in case
2422:                 * we have some trouble initializing union types and have to do more
2423:                 * specific declarations!
2424:                 */
2425:                /* 
2426:                 * Moved global variables to CVMROMGlobals
2427:                 */
2428:                globalHeaderOut
2429:                        .println("    struct scalarTableSegment * dummyNextCell;");
2430:                initInfo.addInfo("NULL", "&CVMROMGlobals.dummyNextCell",
2431:                        "sizeof(CVMROMGlobals.dummyNextCell)");
2432:                auxOut
2433:                        .println("const struct { SCALAR_TABLE_SEGMENT_HEADER struct scalarTableEntry data["
2434:                                + nData + "]; }\nCVMFieldTypeTable = {");
2435:                auxOut.println("\t" + (CVMTypeCode.CVMtypeLastScalar + 1)
2436:                        + ", 0, -1," + nData
2437:                        + ", &CVMROMGlobals.dummyNextCell, {");
2438:                for (int i = 0; i < nData; i++) {
2439:                    CVMDataType o = (CVMDataType) allDataTypes.elementAt(i);
2440:                    /* Yet more debugging output ....
2441:                    if ( o != null && i != o.entryNo ){
2442:                        System.out.println("Datatype entry "+o+" misplaced: is at vector["+i+"] and expected at ["+o.entryNo+"]");
2443:                    }
2444:                     */
2445:                    if (o instanceof  CVMClassDataType) {
2446:                        CVMClassDataType ctype = (CVMClassDataType) o;
2447:                        String next;
2448:                        next = (ctype.next == null) ? "TYPEID_NOENTRY"
2449:                                : ("SCALARTYPE_NO(" + ctype.next.typeNo + ")");
2450:                        // int nameHash = CVMDataType.computeHash(ctype.classInPackage);
2451:                        int nameLength = ctype.classInPackage.length();
2452:                        if (nameLength > 255)
2453:                            nameLength = 255;
2454:                        auxOut.println("	INIT_CLASSTYPE( " + next + ", PKG_NO("
2455:                                + ctype.pkg.entryNo + "), \""
2456:                                + ctype.classInPackage + "\", " + nameLength
2457:                                + "),");
2458:                    } else {
2459:                        CVMArrayDataType atype = (CVMArrayDataType) o;
2460:                        String next;
2461:                        next = (atype.next == null) ? "TYPEID_NOENTRY"
2462:                                : ("SCALARTYPE_NO(" + atype.next.typeNo + ")");
2463:                        auxOut.println("	INIT_ARRAYTYPE( " + next + ", "
2464:                                + atype.depth + ", " + atype.baseType + "),");
2465:                    }
2466:                }
2467:                auxOut.println("}};");
2468:
2469:            }
2470:
2471:            /*
2472:             * The package name data structures and hash tables have to go after the
2473:             * general value-type table, as it contains little hash tables 
2474:             * of pointers to the latter.
2475:             * These are used for lookup by class name.
2476:             */
2477:            private void writeCVMpkgHeader() {
2478:                int nPkg = CVMpkg.pkgVector.size();
2479:                /* 
2480:                 * Moved global variables to CVMROMGlobals
2481:                 */
2482:                globalHeaderOut.println("    struct pkg CVM_ROMpackages["
2483:                        + (nPkg) + "];");
2484:                auxOut
2485:                        .println("#define PKG_NO(n) &CVMROMGlobals.CVM_ROMpackages[n]");
2486:                auxOut.println("const int CVM_nROMpackages = " + nPkg + ";");
2487:            }
2488:
2489:            private void writeCVMpkg() {
2490:                Vector allPackages = CVMpkg.pkgVector;
2491:                int nPkg = allPackages.size();
2492:
2493:                auxOut.println("STATIC const struct pkg CVM_ROMpackagesMaster["
2494:                        + (nPkg) + "] = {");
2495:                for (int i = 0; i < nPkg; i++) {
2496:                    CVMpkg p = (CVMpkg) (allPackages.elementAt(i));
2497:                    writeAnCVMpkg(p);
2498:                    /* DEBUG
2499:                    if ( p.entryNo != i ){
2500:                        System.out.println("Package entry "+p.pkgName+" misplaced: is at vector["+i+"] and expected at ["+p.entryNo+"]");
2501:                    }
2502:                     */
2503:                }
2504:                auxOut.println("};");
2505:
2506:                initInfo.addInfo("CVM_ROMpackagesMaster",
2507:                        "CVMROMGlobals.CVM_ROMpackages", nPkg
2508:                                + "*sizeof(struct pkg)");
2509:
2510:                // that was the packages themselves.
2511:                // this is the hash table that is the basis of looking them up.
2512:                // this needs to be writable, since we add at the front of the
2513:                // linked list.
2514:                auxOut
2515:                        .print("STATIC const struct pkg * const CVM_PkgHashtableMaster["
2516:                                + CVMpkg.NPACKAGEHASH + "] = {");
2517:                for (int i = 0; i < CVMpkg.NPACKAGEHASH; i++) {
2518:                    CVMpkg p = CVMpkg.packages[i];
2519:                    if (i % 5 == 0) {
2520:                        auxOut.print("\n\t");
2521:                    }
2522:                    auxOut.print((p == null) ? "0, "
2523:                            : ("PKG_NO(" + (p.entryNo) + "), "));
2524:                }
2525:                auxOut.println("\n};");
2526:                /* 
2527:                 * Moved globals to CVMROMGlobals.
2528:                 */
2529:                globalHeaderOut.println("    struct pkg *CVM_pkgHashtable["
2530:                        + CVMpkg.NPACKAGEHASH + "];");
2531:                initInfo.addInfo("CVM_PkgHashtableMaster",
2532:                        "CVMROMGlobals.CVM_pkgHashtable", CVMpkg.NPACKAGEHASH
2533:                                + "*sizeof(struct pkg*)");
2534:
2535:                /* 
2536:                 * Made this const (never changed)
2537:                 */
2538:                auxOut
2539:                        .println("struct pkg * const CVMnullPackage = PKG_NO(0);");
2540:            }
2541:
2542:            private void writeAnCVMpkg(CVMpkg p) {
2543:                String next = (p.next == null) ? "0" : ("PKG_NO("
2544:                        + p.next.entryNo + ")");
2545:                //int    nameHash = CVMDataType.computeHash(p.pkgName);
2546:                auxOut.print("    { \"" + p.pkgName + "\", " + next
2547:                        + ", INROM, MAX_COUNT, {");
2548:                for (int i = 0; i < CVMpkg.NCLASSHASH; i++) {
2549:                    String hashp = (p.typeData[i] == null) ? "TYPEID_NOENTRY"
2550:                            : ("SCALARTYPE_NO(" + p.typeData[i].typeNo + ")");
2551:                    if (i % 3 == 0) {
2552:                        auxOut.print("\n\t");
2553:                    }
2554:                    auxOut.print(hashp);
2555:                    auxOut.print(", ");
2556:                }
2557:                auxOut.println("\n    }},");
2558:            }
2559:
2560:            /*
2561:             * The CVMMethodTypes are complex, multi-part beasts.
2562:             * The first part is the Form or Terse Signature,
2563:             * Then we need the details array
2564:             * And finally the table of method types. There are 4 kinds of them!:
2565:             *	0: inline form, inline details;
2566:             *  1: inline form, outboard details;
2567:             *  2: outboard form, inline details (rare);
2568:             *  3: outboard form, outboard details, too.
2569:             * They are all the same size!
2570:             */
2571:            public void writeCVMMethodTypeTable() {
2572:                // The first part is the Form or Terse Signature.
2573:                writeCVMForms();
2574:
2575:                // then the details array.
2576:                writeCVMMethodDetails();
2577:
2578:                // write the indirect dummy.
2579:                /* 
2580:                 * Moved global variables to CVMROMGlobals
2581:                 */
2582:                globalHeaderOut
2583:                        .println("    struct methodTypeTableSegment *methodTypeDummy;");
2584:                initInfo.addInfo("NULL", "&CVMROMGlobals.methodTypeDummy",
2585:                        "sizeof(CVMROMGlobals.methodTypeDummy)");
2586:
2587:                // write the specific declaration we need for this
2588:                // set of types.
2589:                /* 
2590:                 * CVMMethodTypeTable is a structure that holds 
2591:                 * arrays of struct methodTypeTableEntry (see typeid_impl.h)
2592:                 * which are initialized in different ways because 
2593:                 * struct methodTypeTableEntry contains two unions.
2594:                 * 
2595:                 * Unfortunately the original implementation does only
2596:                 * fit for 32 bit platforms (because all four
2597:                 * struct declarations have the same byte size;
2598:                 * unsigned int formdata is as long as struct sigForm *
2599:                 * and unsigned short data[2] is as long as short* datap).
2600:                 * But that does not fit for 64 bit platforms. Therefore
2601:                 * the struct declaration from typeid_impl.h is used to be
2602:                 * sure the initialization is also correct for other platforms.
2603:                 */
2604:                auxOut.println("const struct { METHOD_TABLE_SEGMENT_HEADER");
2605:                for (int i = 0; i < 4; i++) {
2606:                    if (nMethodTypes[i] == 0)
2607:                        continue;
2608:                    auxOut.print("    struct { METHOD_TYPE_HEADER ");
2609:                    if ((i & 2) == 0) {
2610:                        // inline form
2611:                        // This used to be auxOut.print("unsigned int formdata; ");
2612:                        auxOut
2613:                                .print("union {CVMUint32 formdata; struct sigForm * formp;} form; ");
2614:                    } else {
2615:                        // outline form
2616:                        // This used to be auxOut.print("struct sigForm * formp; ");
2617:                        auxOut
2618:                                .print("union {struct sigForm * formp; CVMUint32 formdata;} form; ");
2619:                    }
2620:                    if ((i & 1) == 0) {
2621:                        // inline details
2622:                        // This used to be auxOut.print("unsigned short data[2]; ");
2623:                        auxOut
2624:                                .print("union {CVMTypeIDTypePart data[2]; const CVMTypeIDTypePart * datap; } details; ");
2625:                    } else {
2626:                        // outline details
2627:                        // This used to be auxOut.print("const short* datap; ");
2628:                        auxOut
2629:                                .print("union {const CVMTypeIDTypePart * datap; CVMTypeIDTypePart data[2]; } details; ");
2630:                    }
2631:                    auxOut.print(" }typesig");
2632:                    auxOut.println(i + "[" + nMethodTypes[i] + "];");
2633:                }
2634:                auxOut.println("} CVMMethodTypeTable = {");
2635:
2636:                // now the header info
2637:                /* 
2638:                 * Moved global variables to CVMROMGlobals
2639:                 */
2640:                auxOut.println("    0, 0, -1, " + totalMethodTypes
2641:                        + ", &CVMROMGlobals.methodTypeDummy,");
2642:
2643:                // and the actual data.
2644:                for (int i = 0; i < 4; i++) {
2645:                    if (nMethodTypes[i] == 0)
2646:                        continue;
2647:                    auxOut.println("    {");
2648:                    for (CVMMethodType m = methodTypes[i]; m != null; m = m.listNext) {
2649:                        String next = (m.next == null) ? "TYPEID_NOENTRY"
2650:                                : String.valueOf(m.next.entryNo);
2651:                        auxOut.print("	{" + next + ", MAX_COUNT, ROMSTATE "
2652:                                + (m.form.nSyllables - 2));
2653:                        CVMSigForm f = m.form;
2654:                        if ((i & 2) == 0) {
2655:                            // inline form
2656:                            // This used to be auxOut.print(", 0x"+Integer.toHexString( f.data[0] ));
2657:                            auxOut.print(", {0x"
2658:                                    + Integer.toHexString(f.data[0]) + "}");
2659:                        } else {
2660:                            // outline form
2661:                            // This used to be auxOut.print(", (struct sigForm*)(&CVM_ROMforms.form"+f.listNo+"["+f.entryNo+"])");
2662:                            auxOut
2663:                                    .print(", {(struct sigForm*)(&CVM_ROMforms.form"
2664:                                            + f.listNo
2665:                                            + "["
2666:                                            + f.entryNo
2667:                                            + "])}");
2668:                        }
2669:                        if ((i & 1) == 0) {
2670:                            // inline details
2671:                            auxOut.print(", {{");
2672:                            for (int j = 0; j < 2; j++) {
2673:                                auxOut.print("RAW_TYPEID_TYPE_PART(0x");
2674:                                auxOut
2675:                                        .print(Integer
2676:                                                .toHexString((j < m.nDetails) ? m.details[j]
2677:                                                        : 0));
2678:                                auxOut.print("),");
2679:                            }
2680:                            auxOut.print("}}");
2681:                        } else {
2682:                            // outline details
2683:                            auxOut.print(", {SIG_DETAIL_NO(" + (m.detailOffset)
2684:                                    + ")}");
2685:                        }
2686:                        auxOut.println("},");
2687:                    }
2688:                    auxOut.println("    },");
2689:                }
2690:                auxOut.println("};");
2691:
2692:                /*
2693:                 * A signature search begins with a hash.
2694:                 * The hash table must be writeable.
2695:                 */
2696:                /* 
2697:                 * Moved global variables to CVMROMGlobals
2698:                 */
2699:                globalHeaderOut
2700:                        .println("    CVMTypeIDTypePart CVMMethodTypeHash[NMETHODTYPEHASH];");
2701:                /* 
2702:                 * Added extra precautions to ensure we use the same hash function.
2703:                 */
2704:                auxOut.println("#if NMETHODTYPEHASH != " + CVMMethodType.NHASH);
2705:                auxOut
2706:                        .println("#error \"CVMMethodType.NHASH and NMETHODTYPEHASH are not the same\"");
2707:                auxOut.println("#endif");
2708:
2709:                auxOut
2710:                        .print("STATIC const CVMTypeIDTypePart CVMMethodTypeHashMaster[NMETHODTYPEHASH]={");
2711:
2712:                for (int i = 0; i < CVMMethodType.NHASH; i++) {
2713:                    CVMMethodType mt = CVMMethodType.hashTable[i];
2714:                    if (i % 4 == 0) {
2715:                        auxOut.print("\n	");
2716:                    }
2717:                    if (mt == null) {
2718:                        auxOut.print("TYPEID_NOENTRY, ");
2719:                    } else {
2720:                        auxOut.print(mt.entryNo);
2721:                        auxOut.print(", ");
2722:                    }
2723:                }
2724:                auxOut.println("};");
2725:                /* 
2726:                 * Moved global variables to CVMROMGlobals
2727:                 */
2728:                initInfo
2729:                        .addInfo(
2730:                                "CVMMethodTypeHashMaster",
2731:                                "CVMROMGlobals.CVMMethodTypeHash",
2732:                                CVMMethodType.NHASH
2733:                                        + "*sizeof(CVMROMGlobals.CVMMethodTypeHash[0])");
2734:            }
2735:
2736:            /*
2737:             * Method signature varieties 1 & 3 have details written in an
2738:             * array-of-short.
2739:             */
2740:            private void writeCVMMethodDetails() {
2741:                if (nMethodTypes[1] + nMethodTypes[3] == 0)
2742:                    return; // nothing to do.
2743:                // We could search for shared sub-sequences of detail sequences.
2744:                // On the other hand, these so seldom occur at all
2745:                // that it would make very little difference.
2746:                int curOffset = 0;
2747:                auxOut
2748:                        .print("STATIC const CVMTypeIDTypePart msig_details[] = {");
2749:                for (int i = 1; i < 4; i += 2) { // i.e. for i in {1,3}
2750:                    for (CVMMethodType m = methodTypes[i]; m != null; m = m.listNext) {
2751:                        m.detailOffset = curOffset;
2752:                        int ndetail = m.nDetails;
2753:                        int details[] = m.details;
2754:                        for (int j = 0; j < ndetail; j++) {
2755:                            if (curOffset % 6 == 0) {
2756:                                auxOut.print("\n	");
2757:                            }
2758:                            auxOut.print("RAW_TYPEID_TYPE_PART(0x"
2759:                                    + Integer.toHexString(details[j]) + ")");
2760:                            auxOut.write(',');
2761:                            auxOut.write(' ');
2762:                            curOffset += 1;
2763:                        }
2764:                    }
2765:                }
2766:                auxOut.println("\n};");
2767:            }
2768:
2769:            private void writeCVMForms() {
2770:                /*
2771:                 * Declare a data structure to contain all the "big" forms.
2772:                 * Since they are of varying lengths, this will require a
2773:                 * custom declaration.
2774:                 */
2775:                auxOut.println("STATIC const struct {");
2776:                for (int i = 1; i < CVMSigForm.listLength.length; i++) {
2777:                    if (CVMSigForm.listLength[i] == 0)
2778:                        continue; // never mind...
2779:                    /* 
2780:                     * Added symbol DUMMY (which is never used, but in VC++ on Win32 the preprocessor barks
2781:                     * if it doesn't get an argument here)
2782:                     */
2783:                    auxOut.println("	DECLARE_SIG_FORM_N( DUMMY" + i
2784:                            + " /* never used */, " + (i + 1) + ") form" + i
2785:                            + "[" + CVMSigForm.listLength[i] + "];");
2786:                }
2787:                auxOut.println("} CVM_ROMforms = {");
2788:                /*
2789:                 * Now supply the data. They're all on a single linked list,
2790:                 * which we construct (last-to-first) as we go.
2791:                 */
2792:                String link = "0";
2793:                for (int i = 1; i < CVMSigForm.listLength.length; i++) {
2794:                    int n = CVMSigForm.listLength[i];
2795:                    if (n == 0)
2796:                        continue; // never mind...
2797:                    String segname = "&CVM_ROMforms.form" + i;
2798:                    auxOut.println("    {");
2799:                    int fno = 0;
2800:                    for (CVMSigForm f = CVMSigForm.formList[i]; f != null; f = f.listNext) {
2801:                        auxOut.print("	");
2802:                        auxOut.print("{ (struct sigForm*)" + link
2803:                                + ", MAX_COUNT, ROMSTATE ");
2804:                        auxOut.print((f.nSyllables - 2) + ", { ");
2805:                        int nWordsLess1 = f.data.length - 1;
2806:                        for (int k = 0; k <= nWordsLess1; k++) {
2807:                            auxOut.printHexInt(f.data[k]);
2808:                            if (k < nWordsLess1)
2809:                                auxOut.print(", ");
2810:                        }
2811:                        auxOut.println("} },");
2812:                        //f.listNo  = i;
2813:                        f.entryNo = fno;
2814:                        link = segname + "[" + (fno++) + "]";
2815:                    }
2816:                    auxOut.println("    },");
2817:                }
2818:                auxOut.println("};");
2819:
2820:                /*
2821:                 * Finally, the root of the form list.
2822:                 */
2823:                /* 
2824:                 * Moved globals to CVMROMGlobals.
2825:                 */
2826:                globalHeaderOut.println("    struct sigForm *	CVMformTable;");
2827:                auxOut
2828:                        .println("STATIC const struct sigForm * const CVMformTableMaster = (struct sigForm *)"
2829:                                + link + ";");
2830:                initInfo.addInfo("&CVMformTableMaster",
2831:                        "&CVMROMGlobals.CVMformTable",
2832:                        "sizeof(CVMformTableMaster)");
2833:            }
2834:
2835:            private void writeCVMMemberNameTable() {
2836:                int ndata = CVMMemberNameEntry.tableSize();
2837:                /* 
2838:                 * Moved global variables to CVMROMGlobals
2839:                 */
2840:                globalHeaderOut
2841:                        .println("    struct memberNameTableSegment * dummyNextMembernameCell;");
2842:                initInfo.addInfo("NULL",
2843:                        "&CVMROMGlobals.dummyNextMembernameCell",
2844:                        "sizeof(CVMROMGlobals.dummyNextMembernameCell)");
2845:                auxOut
2846:                        .println("const struct { MEMBER_NAME_TABLE_SEGMENT_HEADER struct memberName data["
2847:                                + ndata + "]; }\nCVMMemberNames = {");
2848:                auxOut.println("    0, 0, -1, " + ndata
2849:                        + ", &CVMROMGlobals.dummyNextMembernameCell, {");
2850:                for (int i = 0; i < ndata; i++) {
2851:                    CVMMemberNameEntry mne = (CVMMemberNameEntry) (CVMMemberNameEntry.table
2852:                            .elementAt(i));
2853:                    String next = (mne.next == null) ? "TYPEID_NOENTRY"
2854:                            : ("NAME_NO(" + mne.next.entryNo + ")");
2855:                    auxOut.println("\t{" + next + ", MAX_COUNT, ROMSTATE \""
2856:                            + mne.name + "\"},");
2857:                }
2858:                auxOut.println("}};");
2859:
2860:                /* 
2861:                 * Moved global variables to CVMROMGlobals
2862:                 */
2863:                globalHeaderOut
2864:                        .println("    CVMTypeIDNamePart CVMMemberNameHash[NMEMBERNAMEHASH];");
2865:
2866:                auxOut
2867:                        .print("STATIC const CVMTypeIDNamePart CVMMemberNameHashMaster[NMEMBERNAMEHASH]={");
2868:                for (int i = 0; i < CVMMemberNameEntry.NMEMBERNAMEHASH; i++) {
2869:                    CVMMemberNameEntry mne = CVMMemberNameEntry.hash[i];
2870:                    if (i % 4 == 0) {
2871:                        auxOut.print("\n	");
2872:                    }
2873:                    if (mne == null) {
2874:                        auxOut.print("TYPEID_NOENTRY, ");
2875:                    } else {
2876:                        auxOut.print(mne.entryNo);
2877:                        auxOut.print(", ");
2878:                    }
2879:                }
2880:                auxOut.println("};");
2881:                /* 
2882:                 * Moved global variables to CVMROMGlobals
2883:                 */
2884:                initInfo
2885:                        .addInfo(
2886:                                "CVMMemberNameHashMaster",
2887:                                "CVMROMGlobals.CVMMemberNameHash",
2888:                                CVMMemberNameEntry.NMEMBERNAMEHASH
2889:                                        + "*sizeof(CVMROMGlobals.CVMMemberNameHash[0])");
2890:            }
2891:
2892:            /* Write the invokeCost array for romized methods. */
2893:            private void writeMethodInvokeCostArray() {
2894:                globalHeaderOut
2895:                        .println("#if defined(CVM_JIT) && defined(CVM_MTASK)");
2896:                globalHeaderOut
2897:                        .println("    CVMUint16 CVMROMMethodInvokeCosts["
2898:                                + nTotalMethods + "];");
2899:                globalHeaderOut.println("#endif");
2900:                auxOut.println("#if defined(CVM_JIT) && defined(CVM_MTASK)");
2901:                auxOut.println("const int CVM_nROMMethods = " + nTotalMethods
2902:                        + ";");
2903:                auxOut.println("#endif");
2904:            }
2905:
2906:            class ClassTable {
2907:                String name;
2908:                int nClasses;
2909:                CVMClass classVector[];
2910:                boolean foundFirstVector;
2911:                boolean foundLastVector;
2912:                boolean foundFirstNonPrimitive;
2913:                int firstVector;
2914:                int lastVector;
2915:                int firstNonPrimitive;
2916:
2917:                ClassTable(int nMax, String nm) {
2918:                    name = nm;
2919:                    classVector = new CVMClass[nMax];
2920:                    nClasses = 0;
2921:                    foundFirstVector = false;
2922:                    foundLastVector = false;
2923:                }
2924:
2925:                void addClass(CVMClass c) {
2926:                    int hashCode = 0;
2927:                    int classid = c.classid();
2928:                    if ((!foundFirstNonPrimitive) & !c.isPrimitiveClass()) {
2929:                        firstNonPrimitive = nClasses;
2930:                        foundFirstNonPrimitive = true;
2931:                    }
2932:                    int classid_depth = classid & CVMTypeCode.CVMtypeArrayMask;
2933:                    if ((classid_depth != 0)
2934:                            && (classid_depth != CVMTypeCode.CVMtypeBigArray)) {
2935:                        if (!foundFirstVector) {
2936:                            firstVector = nClasses;
2937:                            foundFirstVector = true;
2938:                        }
2939:                        if (((classid >> CVMTypeCode.CVMtypeArrayShift) > 1)
2940:                                && !foundLastVector) {
2941:                            lastVector = nClasses - 1;
2942:                            foundLastVector = true;
2943:                        }
2944:                    }
2945:                    classVector[nClasses++] = c;
2946:                }
2947:
2948:                void writeClasslistInfo() {
2949:                    if (!foundFirstVector) {
2950:                        // If, by now, we've not found the first vector, then there is no
2951:                        //     preloaded array type.  Point the first vector to the end of
2952:                        //     the array:
2953:                        firstVector = nClasses;
2954:                        foundFirstVector = true;
2955:                        lastVector = nClasses;
2956:                        foundLastVector = true;
2957:                    } else if (!foundLastVector) {
2958:                        // If we get here, then we must have found the first vector but
2959:                        //     have not found the last vector.  This means that there are
2960:                        //     array types of depth 1 in the list but no array types of
2961:                        //     depth greater than 1.  Point the last vector to the last
2962:                        //     entry in the list:
2963:                        lastVector = nClasses - 1;
2964:                        foundLastVector = true;
2965:                    }
2966:                    auxOut.println("const int CVM_n" + name + "ROMClasses = "
2967:                            + String.valueOf(nClasses) + ";");
2968:                    auxOut.print("const int CVM_" + name
2969:                            + "firstROMVectorClass = ");
2970:                    auxOut.print(firstVector);
2971:                    auxOut.print(";\nconst int CVM_" + name
2972:                            + "lastROMVectorClass = ");
2973:                    auxOut.print(lastVector);
2974:                    auxOut.println(";");
2975:                    auxOut.print("const int CVM_" + name
2976:                            + "firstROMNonPrimitiveClass = ");
2977:                    auxOut.print(firstNonPrimitive);
2978:                    auxOut.println(";");
2979:                }
2980:
2981:                void writeClasslist() {
2982:                    int n = nClasses;
2983:                    CVMClass classes[] = classVector;
2984:                    //auxOut.println("const CVMClassBlock * const CVM_"+name+"ROMClassBlocks[] = {" );
2985:                    for (int i = 0; i < n; i++) {
2986:                        CVMClass c = classVector[i];
2987:                        auxOut.print("    &");
2988:                        auxOut.print(cbName(c));
2989:                        auxOut.println(",");
2990:                    }
2991:                    //auxOut.println("};");
2992:                }
2993:
2994:            }
2995:
2996:            public void writeClassList() {
2997:                boolean foundFirstNonPrimitive = false;
2998:                int firstNonPrimitive = 0;
2999:                int n = (classes == null) ? 0 : classes.length;
3000:                ClassTable classTable = new ClassTable(n, "");
3001:                globalHeaderOut
3002:                        .println("    struct java_lang_Class CVM_ROMClassBlocks["
3003:                                + String.valueOf(n) + "];");
3004:                auxOut.println("const int CVM_nTotalROMClasses = "
3005:                        + String.valueOf(n) + ";");
3006:                /* 
3007:                 * Moved globals to CVMROMGlobals
3008:                 */
3009:                globalHeaderOut
3010:                        .println("    struct java_lang_Class CVM_ROMClasses["
3011:                                + n + "];");
3012:                for (int i = 0; i < n; i++) {
3013:                    int hashCode = 0;
3014:                    CVMClass c = classes[i];
3015:                    int classid = c.classid();
3016:                    classTable.addClass(c);
3017:                }
3018:                auxOut
3019:                        .println("const CVMClassBlock * const CVM_ROMClassblocks[] = {");
3020:                classTable.writeClasslist();
3021:                auxOut.println("};");
3022:                classTable.writeClasslistInfo();
3023:
3024:                //
3025:                // array of stack map indirect cells
3026:                //
3027:                /* 
3028:                 * Moved global variables to CVMROMGlobals
3029:                 */
3030:                declare("const CVMClassICell CVM_classICell[]", auxOut);
3031:                auxOut.println(" = {");
3032:                for (int i = 0; i < n; i++) {
3033:                    auxOut
3034:                            .println("    { (CVMObject*)(&CVMROMGlobals.CVM_ROMClasses["
3035:                                    + i + "])},");
3036:                }
3037:                auxOut.println("};");
3038:            }
3039:
3040:            public boolean writeClasses(ConstantPool sharedconsts,
3041:                    boolean doWrite) {
3042:
3043:                // getClassVector sorts the classes with
3044:                // super before sub, for reasonable processing without recursion.
3045:                ClassClass arrayOfClasses[] = ClassClass
3046:                        .getClassVector(classMaker);
3047:                ClassClass.setTypes();
3048:                int nClasses = arrayOfClasses.length;
3049:
3050:                classes = new CVMClass[nClasses];
3051:
3052:                if (sharedconsts != null) {
3053:                    doShared = true;
3054:                    sharedConstantPoolName = "CVMSharedConstantPool";
3055:                    sharedConstantPoolSize = sharedconsts.getLength();
3056:                    if (sharedConstantPoolSize > 0xffff) {
3057:                        // More than 64K constants are not allowed
3058:                        throw new Error("Constant pool overflow: 64k constants"
3059:                                + " allowed, have " + sharedConstantPoolSize);
3060:                    }
3061:                }
3062:
3063:                /*
3064:                 * sort the array by classid. This makes it easier do lookups
3065:                 * at runtime.
3066:                 * The mechanics of this whole writer assume a single
3067:                 * ordering for these classes, as they are often
3068:                 * referred to by their class number.
3069:                 * This is it.
3070:                 * To avoid finding the primitive classes at all, they are
3071:                 * placed at the very end.
3072:                 */
3073:                System.arraycopy(arrayOfClasses, 0, classes, 0, nClasses);
3074:                Arrays.sort(classes, (java.util.Comparator) classMaker);
3075:
3076:                enumerateMethodTypes();// after all classes processed once by classMaker
3077:                // ... but before we write the classes.
3078:
3079:                // write out some constant pool stuff here,
3080:                // if we're doing one big shared one...
3081:                // gutted out for now...
3082:                if (doShared)
3083:                    processStrings(sharedconsts);
3084:
3085:                if (verbose && doWrite) {
3086:                    System.out.println(Localizer
3087:                            .getString("cwriter.writing_classes"));
3088:                }
3089:                try {
3090:                    //mungeAllIDsAndWriteExternals(classes);
3091:                    for (int i = 0; i < nClasses; i++) {
3092:                        classProcessStrings(classes[i].ci, doShared);
3093:                    }
3094:
3095:                    if (doWrite) {
3096:                        instantiateAllStrings();
3097:                        CVMInterfaceMethodTable.writeInterfaceTables(classes,
3098:                                auxOut, headerOut);
3099:                        int nStaticWords = writeStaticStore(classes);
3100:
3101:                        /* The number of necessary slots for clinitEE + 1.
3102:                         * Index of a class that doesn't have <clinit> is always 0.
3103:                         * The 0th entry is reserved for it. */
3104:                        int maxClinitIdx = 1;
3105:                        /*
3106:                         * First off, check compression opportunities. Look over all
3107:                         * methods to see variations
3108:                         */
3109:                        for (int i = 0; i < nClasses; i++) {
3110:                            CVMClass c = classes[i];
3111:                            analyzeMethodsForCompression(c);
3112:                        }
3113:                        //
3114:                        // Sort in order of decreasing refcount
3115:                        //
3116:                        methStats.sort();
3117:                        //
3118:                        // This is shared between our segments
3119:                        //
3120:                        methStats.dump(auxOut);
3121:                        /*
3122:                         * Now do the writing 
3123:                         */
3124:                        for (int i = 0; i < nClasses; i++) {
3125:                            CVMClass c = classes[i];
3126:                            int clinitIdx = c.hasStaticInitializer ? maxClinitIdx++
3127:                                    : 0;
3128:                            writeClass(i, c, clinitIdx, nStaticWords);
3129:                            if (segmentedOutput && (curClasses++ >= maxClasses)) {
3130:                                curClasses = 0;
3131:                                openNextClassFile();
3132:                            }
3133:                        }
3134:
3135:                        if (doShared) {
3136:                            // Dump the shared constant pool
3137:                            writeConstants(sharedconsts,
3138:                                    sharedConstantPoolName, true /* export c.p. ref */);
3139:                        }
3140:
3141:                        writeClassList();
3142:
3143:                        writeCVMNameAndTypeTables();
3144:
3145:                        /* Write method invokeCost array */
3146:                        writeMethodInvokeCostArray();
3147:
3148:                        initInfo.write(auxOut,
3149:                                "struct CVM_preloaderInitTriple",
3150:                                "CVM_preloaderInitMap");
3151:                        initInfoForMBs.write(auxOut, "void* const",
3152:                                "CVM_preloaderInitMapForMbs");
3153:
3154:                        auxOut
3155:                                .println("const char *CVMROMClassLoaderNames = \""
3156:                                        + components.ClassTable
3157:                                                .getClassLoaderNames() + "\";");
3158:                        auxOut
3159:                                .println("CVMAddr * const CVMROMClassLoaderRefs = "
3160:                                        + "STATIC_STORE_ADDRESS("
3161:                                        + clRefOff
3162:                                        + ");");
3163:                        auxOut.println("const int CVMROMNumClassLoaders = "
3164:                                + components.ClassTable.getNumClassLoaders()
3165:                                + ";");
3166:                    }
3167:                } catch (java.io.IOException e) {
3168:                    failureMode = e;
3169:                    formatError = true;
3170:                } finally {
3171:                    if (doWrite) {
3172:                        classOut.flush();
3173:                        headerOut.flush();
3174:                    }
3175:                }
3176:                return (!formatError)
3177:                        && (!doWrite || ((!classOut.checkError()) && (!headerOut
3178:                                .checkError())));
3179:            }
3180:
3181:            public boolean writeClasses(boolean doWrite) {
3182:                return writeClasses(null, doWrite);
3183:            }
3184:
3185:            public void printSpaceStats(java.io.PrintStream o) {
3186:                //ClassClass classes[] = ClassClass.getClassVector( classMaker );
3187:                o.println("	"
3188:                        + Localizer.getString("cwriter.total_classes", Integer
3189:                                .toString(classes.length)));
3190:                o.println("		... of which " + nClinits
3191:                        + " classes have static initializers ");
3192:                o.println("		    (" + CodeHacker.checkinitQuickenings + "/"
3193:                        + CodeHacker.quickenings + " quickening sites)");
3194:                o.println("		"
3195:                        + Localizer.getString("cwriter.method_blocks", Integer
3196:                                .toString(nmethods)));
3197:                if (nWritableMethodBlocks != 0) {
3198:                    o.println("		... of which " + nWritableMethodBlocks
3199:                            + " blocks are writable");
3200:                    o.println("		... for " + nClassesWithWritableMethodBlocks
3201:                            + " classes");
3202:                }
3203:                if (nMethodsWithCheckinitInvokes > 0) {
3204:                    o.println("		... of which " + nMethodsWithCheckinitInvokes
3205:                            + " have checkinit opcodes in the code");
3206:                }
3207:                o.println("		"
3208:                        + Localizer.getString("cwriter.bytes_java_code",
3209:                                Integer.toString(ncodebytes)));
3210:                o.println("		"
3211:                        + Localizer.getString("cwriter.catch_frames", Integer
3212:                                .toString(ncatchframes)));
3213:                o.println("		"
3214:                        + Localizer.getString("cwriter.field_blocks", Integer
3215:                                .toString(nfields)));
3216:                o.println("		"
3217:                        + Localizer.getString("cwriter.inner_classes", Integer
3218:                                .toString(ninnerclasses)));
3219:                o.println("		"
3220:                        + Localizer.getString("cwriter.constant_pool_entries",
3221:                                Integer.toString(nconstants)));
3222:                o.println("		"
3223:                        + Localizer.getString("cwriter.java_strings", Integer
3224:                                .toString(njavastrings)));
3225:            }
3226:
3227:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.