Source Code Cross Referenced for EVMMethodInfo.java in  » 6.0-JDK-Modules » j2me » vm » 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 » vm 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *   
0003:         *
0004:         * Copyright  1990-2007 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 vm;
0028:
0029:        /*
0030:         * VM-specific internal representation of
0031:         * a method. Target-machine independent.
0032:         *
0033:         * See also EVMClass for VM-specific info associated with each class.
0034:         * See also EVMVM for VM-specific info not associated directly with any class.
0035:         */
0036:        import components.*;
0037:        import vm.VMMethodInfo;
0038:        import jcc.Const;
0039:        import jcc.EVMConst;
0040:        import util.DataFormatException;
0041:        import java.util.Enumeration;
0042:        import java.util.Vector;
0043:        import java.util.Hashtable;
0044:        import java.util.StringTokenizer;
0045:
0046:        public class EVMMethodInfo extends VMMethodInfo implements  Const,
0047:                EVMConst {
0048:            private boolean impureCode = false;
0049:            private boolean mustAlign = false;
0050:            private boolean codeExamined = false;
0051:            public MethodInfo method;
0052:
0053:            private String myNativeName;
0054:
0055:            private int inlining;
0056:            static final int NO_INLINE_FLAG = (0x1 << 24);
0057:            static final int SAME_CLASS_FLAG = (0x1 << 25);
0058:            static final int REDO_INLINING_FLAG = (0x1 << 26);
0059:
0060:            /** Keep this var to make code look the same as in inline.c */
0061:            static final boolean UseLosslessQuickOpcodes = false;
0062:
0063:            /**
0064:             * Flag used in quickenCode() to save old methodblock info so we can
0065:             * use it here for inlining.  This affects invokevirtual_quick which
0066:             * typically overwrites the methodblock info with <methodtable offset>
0067:             * and <nargs>.
0068:             */
0069:            public static final boolean SAVE_TARGET_METHODS = true;
0070:
0071:            public EVMMethodInfo(MethodInfo m) {
0072:                method = m;
0073:                method.vmMethodInfo = this ;
0074:            }
0075:
0076:            private void examineCode() throws DataFormatException {
0077:                impureCode = false;
0078:                mustAlign = false;
0079:                if (method.code == null) {
0080:                    codeExamined = true;
0081:                    return;
0082:                }
0083:                byte[] code = method.code;
0084:                int ncode = code.length;
0085:                int opcode;
0086:                for (int i = 0; i < ncode; i += method.opcodeLength(i)) {
0087:                    switch (opcode = (int) code[i] & 0xff) {
0088:
0089:                    case opc_tableswitch:
0090:                    case opc_lookupswitch:
0091:                        mustAlign = true;
0092:                        break;
0093:
0094:                    case opc_ldc:
0095:                    case opc_ldc_w:
0096:                    case opc_ldc2_w:
0097:                    case opc_getstatic:
0098:                    case opc_putstatic:
0099:                    case opc_getfield:
0100:                    case opc_putfield:
0101:                    case opc_invokevirtual:
0102:                    case opc_invokespecial:
0103:                    case opc_invokestatic:
0104:                    case opc_invokeinterface:
0105:                    case opc_new:
0106:                    case opc_anewarray:
0107:                    case opc_checkcast:
0108:                    case opc_instanceof :
0109:                    case opc_multianewarray:
0110:                        impureCode = true; // all get quicked.
0111:                        break;
0112:                    }
0113:                }
0114:                codeExamined = true;
0115:            }
0116:
0117:            public boolean isCodePure() throws DataFormatException {
0118:                if (!codeExamined) {
0119:                    examineCode(); // may throw exception without setting codeExamined
0120:                }
0121:                return !impureCode;
0122:            }
0123:
0124:            public int alignment() throws DataFormatException {
0125:                if (!codeExamined) {
0126:                    examineCode(); // may throw exception without setting codeExamined
0127:                }
0128:                return mustAlign ? 4 : 1;
0129:            }
0130:
0131:            private static int methodNumber = 0;
0132:
0133:            public String getNativeName() {
0134:                if (myNativeName == null) {
0135:                    // need to take parameter list into account.
0136:                    // OR just enumerate, as the actual name doesn't matter.
0137:                    // IMPL_NOTE: consider whether this should be fixed. 
0138:                    myNativeName = ((EVMClass) (method.parent.vmClass))
0139:                            .getNativeName()
0140:                            + methodNumber;
0141:                    methodNumber += 1;
0142:                }
0143:                return myNativeName;
0144:            }
0145:
0146:            public boolean hasBody() {
0147:                return ((method.access & (ACC_ABSTRACT | ACC_NATIVE)) == 0);
0148:            }
0149:
0150:            public int EVMflags() {
0151:                int flagval = 0;
0152:                int a = method.access;
0153:                if ((a & ACC_PUBLIC) != 0)
0154:                    flagval |= EVM_METHOD_ACC_PUBLIC;
0155:                if ((a & ACC_PRIVATE) != 0)
0156:                    flagval |= EVM_METHOD_ACC_PRIVATE;
0157:                if ((a & ACC_PROTECTED) != 0)
0158:                    flagval |= EVM_METHOD_ACC_PROTECTED;
0159:                if ((a & ACC_STATIC) != 0)
0160:                    flagval |= EVM_METHOD_ACC_STATIC;
0161:                if ((a & ACC_FINAL) != 0)
0162:                    flagval |= EVM_METHOD_ACC_FINAL;
0163:                if ((a & ACC_SYNCHRONIZED) != 0)
0164:                    flagval |= EVM_METHOD_ACC_SYNCHRONIZED;
0165:                if ((a & ACC_NATIVE) != 0)
0166:                    flagval |= EVM_METHOD_ACC_NATIVE;
0167:                if ((a & ACC_ABSTRACT) != 0)
0168:                    flagval |= EVM_METHOD_ACC_ABSTRACT;
0169:                return flagval;
0170:
0171:            }
0172:
0173:            public int methodOffset() {
0174:                int off = method.methodTableIndex;
0175:                if (off < 0) {
0176:                    /*
0177:                     * off < 0 means that we do not have a methodtable or
0178:                     * imethodtable entry for this method. This is ok if it is:
0179:                     * - private, or
0180:                     * - static, or
0181:                     * - <init>
0182:                     * Otherwise, this is an error.
0183:                     */
0184:                    if (method.isStaticMember() || method.isPrivateMember()
0185:                            || method.name.string.equals("<init>")) {
0186:                        return 0;
0187:                    } else {
0188:                        throw new Error("Bad method offset for "
0189:                                + method.qualifiedName());
0190:                    }
0191:                }
0192:                return off;
0193:            }
0194:
0195:            /** Attempt to inline the code of this method */
0196:            final static int inline_NOT_DONE = 0;
0197:            final static int inline_IN_PROGRESS = 1;
0198:            final static int inline_DONE = 2;
0199:
0200:            private int inlineState = inline_NOT_DONE;
0201:
0202:            public void inlineCode() {
0203:                new Error().printStackTrace();
0204:
0205:                boolean isRewritten = false;
0206:                if (inlineState == inline_NOT_DONE) {
0207:                    inlineState = inline_IN_PROGRESS;
0208:                } else {
0209:                    return;
0210:                }
0211:                ConstantObject[] cp = method.parent.constants;
0212:                byte[] code = method.code;
0213:                byte[] rewrite;
0214:                int tmi = 0; // target method index
0215:
0216:                for (int pc = 0; pc < code.length;) {
0217:                    int opcode = code[pc] & 0xff;
0218:
0219:                    switch (opcode) {
0220:
0221:                    case opc_invokevirtual_fast:
0222:                    case opc_invokespecial_fast:
0223:                    case opc_invokestatic_fast: {
0224:                        int index = method.getUnsignedShort(pc + 1);
0225:                        MethodConstant mc = (MethodConstant) cp[index];
0226:                        VMMethodInfo targetMethod = mc.find().vmMethodInfo;
0227:                        rewrite = MethodCallInline(pc,
0228:                                (EVMMethodInfo) targetMethod);
0229:                        if (rewrite != null) {
0230:                            isRewritten = true;
0231:                            System.arraycopy(rewrite, 0, code, pc, 3);
0232:                        }
0233:                        pc += 3;
0234:                        break;
0235:                    }
0236:
0237:                    default:
0238:                        pc += method.opcodeLength(pc);
0239:                        break;
0240:                    }
0241:                }
0242:                if (isRewritten)
0243:                    compress();
0244:                inlineState = inline_DONE;
0245:            }
0246:
0247:            /* This method is called to determine whether the method "mb" called at
0248:             * from instruction "pc" can be inlined.  If not, the value null is
0249:             * returned.  If so, an array of three bytes, which should overwrite the
0250:             * method invocation, is returned
0251:             */
0252:            private byte[] MethodCallInline(int pc, EVMMethodInfo mb) {
0253:                byte code[] = method.code;
0254:                int opcode = code[pc] & 0xff;
0255:
0256:                if (opcode == opc_invokevirtual_fast) {
0257:                    /* This is a virtual method call.  No use even bother trying to
0258:                     * inline the method, unless its final
0259:                     */
0260:                    if (((mb.method.access & ACC_FINAL) == 0)
0261:                            && ((mb.method.parent.access & ACC_FINAL) == 0))
0262:                        return null;
0263:                }
0264:
0265:                int mbInlining = mb.getInlining();
0266:                if ((mbInlining & NO_INLINE_FLAG) != 0)
0267:                    return null;
0268:                /* Does this inlining have a dependency on the constant pool, and so
0269:                 * can only be used on a method in the same class. */
0270:                if ((mbInlining & SAME_CLASS_FLAG) != 0) {
0271:                    if (this .method.parent != mb.method.parent)
0272:                        return null;
0273:                }
0274:                /* There is a inlining.  Copy that value into "result" */
0275:                byte[] result = new byte[3];
0276:                result[0] = INLINING_WORD1(mbInlining);
0277:                result[1] = INLINING_WORD2(mbInlining);
0278:                result[2] = INLINING_WORD3(mbInlining);
0279:                return result;
0280:            }
0281:
0282:            public int getInlining() {
0283:                MethodInfo mi = this .method;
0284:                if (inlining == 0) {
0285:                    if (((mi.access & (ACC_ABSTRACT | ACC_NATIVE | ACC_SYNCHRONIZED)) != 0)
0286:                            || (mi.exceptionTable.length > 0)) {
0287:                        inlining = NO_INLINE_FLAG;
0288:                    } else {
0289:                        inlineCode();
0290:                        inlining = calculateInlining();
0291:
0292:                        /*******
0293:                        if (inlining != NO_INLINE_FLAG) { 
0294:                            String sameClass = 
0295:                        	((inlining & SAME_CLASS_FLAG) != 0) ? "*" : "";
0296:                            System.out.print("get: " + this + " =>" + sameClass);
0297:                            System.out.println(" " + disassembleInlining());
0298:                        }
0299:                         ********/
0300:                    }
0301:                }
0302:                return inlining;
0303:            }
0304:
0305:            /* Given a method, determine if it can be "inlined" into three or fewer
0306:             * bytes.
0307:             */
0308:            private int calculateInlining() {
0309:                MethodInfo mb = this .method;
0310:                byte[] code = mb.code;
0311:
0312:                /* The checkThis flag indicates that the resulting code must 
0313:                 * throw a NullPointerException if the first argument is null
0314:                 */
0315:                boolean checkThis = ((mb.access & ACC_STATIC) == 0)
0316:                        && !method.name.string.equals("<init>");
0317:
0318:                boolean redoInlining = false;
0319:                int stackSize, stackBase;
0320:                OpcodeInfoType opPtr;
0321:
0322:                stackSize = 0;
0323:                stackBase = 0; // Prevent javac warning
0324:                for (int pc = 0;; pc++) {
0325:                    /* At this point in our simulation of the execution of the
0326:                     * method, registers stackBase .. stackBase+stackSize - 1 are
0327:                     * pushed onto the the stack.  pc points to the next
0328:                     * instruction to look at.
0329:                     */
0330:                    int opcode = code[pc] & 0xff;
0331:                    int opcode2;
0332:                    int reg, regSize, nextReg;
0333:
0334:                    if (stackSize == 0)
0335:                        stackBase = 0;
0336:                    nextReg = stackBase + stackSize;
0337:                    opPtr = OpcodeInfo[opcode];
0338:
0339:                    switch (opPtr.opcode) {
0340:
0341:                    case opc_iload_0: /* register load.  regnum from opcode */
0342:                    case opc_iload: /* register load.  regnum from pc[1] */
0343:                        if (opPtr.opcode == opc_iload_0) {
0344:                            reg = REGNUM(opPtr);
0345:                        } else {
0346:                            reg = code[pc + 1] & 0xff;
0347:                            pc++;
0348:                        }
0349:                        regSize = REGSIZE(opPtr);
0350:                        if (stackSize == 0) /* stack is currently empty */
0351:                            stackBase = reg;
0352:                        else if (nextReg != reg)
0353:                            return NO_INLINE_FLAG;
0354:                        stackSize += regSize;
0355:                        continue;
0356:
0357:                    case opc_pop: /* pop stack, or nop */
0358:                        stackSize -= REGSIZE(opPtr);
0359:                        continue;
0360:
0361:                    case opc_nonnull_quick: /* special instruction */
0362:                        if (nextReg == 1) {
0363:                            /* We're checking register 0 to ensure that it isn't null */
0364:                            stackSize = 0;
0365:                            checkThis = true;
0366:                            continue;
0367:                        }
0368:                        return NO_INLINE_FLAG;
0369:
0370:                    case opc_invokeignored_quick: /* special instruction */
0371:                    {
0372:                        int popCount = code[pc + 1] & 0xff;
0373:                        if (code[pc + 2] != 0) {
0374:                            /* We only know how to check register 0 for non-null ness */
0375:                            if (nextReg != popCount)
0376:                                return NO_INLINE_FLAG;
0377:                            checkThis = true;
0378:                            stackSize -= popCount;
0379:                        } else {
0380:                            stackSize -= popCount;
0381:                        }
0382:                        pc += 2;
0383:                        continue;
0384:                    }
0385:
0386:                    case opc_return: /* return void or value */
0387:                        return makeReturnResult(checkThis, nextReg,
0388:                                REGSIZE(opPtr));
0389:
0390:                    case opc_iadd: { /* any simple instruction */
0391:                        int ilength = opcLengths[opcode];
0392:                        int result;
0393:                        opcode2 = code[pc + ilength] & 0xff;
0394:
0395:                        if (!((opPtr.outStack > 0) ? isXreturn(opcode2)
0396:                                : (opcode2 == opc_return || opcode == opc_athrow)))
0397:                            return NO_INLINE_FLAG;
0398:
0399:                        if ((opPtr.flags & OpcodeInfoType.NULL_CHECK) != 0
0400:                                && (stackBase == 0)) {
0401:                            /* We don't need to generate code to check for null, since
0402:                             * the instruction already does it.
0403:                             */
0404:                            checkThis = false;
0405:                        }
0406:                        switch (ilength) {
0407:                        case 1:
0408:                            result = makeOpcodeResult(checkThis, nextReg,
0409:                                    opPtr.inStack, 1, opcode, 0, 0);
0410:                            break;
0411:                        case 2:
0412:                            result = makeOpcodeResult(checkThis, nextReg,
0413:                                    opPtr.inStack, 2, opcode,
0414:                                    code[pc + 1] & 0xff, 0);
0415:                            break;
0416:                        case 3:
0417:                            result = makeOpcodeResult(checkThis, nextReg,
0418:                                    opPtr.inStack, 3, opcode,
0419:                                    code[pc + 1] & 0xff, code[pc + 2] & 0xff);
0420:                            break;
0421:                        default:
0422:                            throw new RuntimeException("sysAssert(FALSE);");
0423:                            // result = NO_INLINE_FLAG; // not reached
0424:                            // break;			// not reached
0425:                        }
0426:                        if ((result & NO_INLINE_FLAG) == 0) {
0427:                            if ((opPtr.flags & OpcodeInfoType.CONSTANT_POOL) != 0)
0428:                                result |= SAME_CLASS_FLAG;
0429:                            if (redoInlining)
0430:                                result |= REDO_INLINING_FLAG;
0431:                        }
0432:                        return result;
0433:                    }
0434:
0435:                    default:
0436:                        throw new RuntimeException("sysAssert(FALSE);");
0437:                    case 255: /* random instruction */
0438:                        return NO_INLINE_FLAG;
0439:
0440:                    } /* of switch statement */
0441:                } /* end of for loop */
0442:            }
0443:
0444:            /* This method is called to create the code that is actually going to
0445:             * replace the indicated method, when the method does nothing, or when
0446:             * it simply returns one of its arguments.
0447:             *
0448:             * It takes the following arguments:
0449:             *   mb:          Method we are examining
0450:             *   checkThis:   If true,  We must specially check that the first argument
0451:             *                "this" isn't null. 
0452:             *   highReg,     One greater than the highest register on the stack when
0453:             *                the return or Xreturn is called.
0454:             *   returnSize   Size of the return (0 for return, 1 for ireturn, 
0455:             *                 2 for lreturn, etc);
0456:             *
0457:             * We have to emulate the method call in 3 bytes.  At the time the
0458:             * method is called, the arguments reg[0] . . . reg[mb->args_size - 1]
0459:             * are pushed on the stack.
0460:             */
0461:            static int[] poppers = { opc_nop, opc_pop, opc_pop2 };
0462:
0463:            private int makeReturnResult(boolean checkThis, int highReg,
0464:                    int returnSize) {
0465:                MethodInfo mb = method;
0466:                int argsSize = mb.argsSize;
0467:                if (returnSize == 0) {
0468:                    /* Return void */
0469:                    return MAKE_INLINING(opc_invokeignored_quick, argsSize,
0470:                            (checkThis ? 1 : 0));
0471:                } else {
0472:                    /* Return some value from the stack */
0473:                    int returnReg = highReg - returnSize;
0474:                    int excessArgs = argsSize - returnSize - returnReg;
0475:                    // sysAssert(returnReg >= 0 && returnSize >= 0);
0476:                    if (returnReg == 0) {
0477:                        /* Returning reg0 or reg0/reg1 */
0478:                        if (checkThis) {
0479:                            /* Must be returning reg0, which is also checked. We
0480:                             * require argsSize >= 2 (which is the same thing as
0481:                             * excessArgs >= 1), because otherwise the "dup" might
0482:                             * overflow the stack.  More sophisticated inliners
0483:                             * might see if there is space on the caller's stack.
0484:                             */
0485:                            // sysAssert(returnSize == 1);
0486:                            if (argsSize < 2) {
0487:                                return NO_INLINE_FLAG;
0488:                            } else if (excessArgs > 2) {
0489:                                return NO_INLINE_FLAG;
0490:                            } else {
0491:                                return MAKE_INLINING(poppers[excessArgs],
0492:                                        opc_dup, opc_nonnull_quick);
0493:                            }
0494:                        } else {
0495:                            /* We're returning reg0 or reg0/reg1 which isn't null
0496:                             * checked.  We just pop extraneous stuff off the stack
0497:                             * */
0498:                            return MAKE_INLINING(opc_invokeignored_quick,
0499:                                    excessArgs, 0);
0500:                        }
0501:                    } else {
0502:                        /* At this point, returnReg > 0.  We're returning something
0503:                         * other than the bottom of the stack.
0504:                         */
0505:                        if (returnSize == 1 && returnReg == 1) {
0506:                            if (excessArgs > 2) {
0507:                                return NO_INLINE_FLAG;
0508:                            }
0509:                            return MAKE_INLINING(poppers[excessArgs], opc_swap,
0510:                                    checkThis ? opc_nonnull_quick : opc_pop);
0511:                        }
0512:                        return NO_INLINE_FLAG;
0513:                    }
0514:                }
0515:            }
0516:
0517:            /* This method is called to create the code that is actually going to
0518:             * replace the indicated method
0519:             * 
0520:             * makeOpcodeResult is used to create a inlining that can be used anywhere
0521:             * It takes the following arguments:
0522:             *
0523:             *   mb:          Method we are examining
0524:             *   checkThis:   If true,  We must specially check that the first argument
0525:             *                "this" isn't null.  This condition is >>NOT<< tested by 
0526:             *                the generated code.
0527:             *   nextReg:     In the emulation, the highest register on the stack is
0528:             *                reg[nextReg - 1].
0529:             *   icount       The number of bytes of instructions that follow.
0530:             *   opcode, op1, op2
0531:             *                The bytes of instruction.
0532:             *
0533:             * We have to emulate the method call in 3 bytes.  At the time the
0534:             * method is called, the arguments reg[0] . . . reg[mb->args_size - 1]
0535:             * are pushed on the stack.  So in three bytes, we have to:
0536:             *     Remove any excess arguments from the stack.
0537:             *     Perform the operation on the indicated stack registers
0538:             *     Remove any objects lower down on the stack (this is hard!)
0539:             *     Make sure that reg[0] is checked for being non-null, if necessary.
0540:             */
0541:            private int makeOpcodeResult(boolean checkThis, int nextReg,
0542:                    int opcodeArgCount, int icount, int opcode, int op1, int op2) {
0543:                MethodInfo mb = method;
0544:                int firstReg = (opcodeArgCount == 0) ? 0 : nextReg
0545:                        - opcodeArgCount;
0546:                // sysAssert(firstReg >= 0 && opcodeArgCount >= 0 && icount > 0);
0547:
0548:                if (firstReg > 0) {
0549:                    /* There are extra registers at the bottom of the stack */
0550:                    return makePoppingResult(checkThis, firstReg,
0551:                            opcodeArgCount, icount, opcode, op1, op2);
0552:                } else {
0553:                    /* No extra registers at bottom of stack */
0554:                    int argsSize = mb.argsSize;
0555:                    int excessArgs = argsSize - opcodeArgCount; /* extra at top */
0556:                    int popSpace = 3 - icount; /* space to pop args at top */
0557:
0558:                    int result = 0;
0559:                    int i;
0560:
0561:                    if (checkThis) {
0562:                        /* Unless this is a constant method that ignores all of its
0563:                         * arguments, we don't really have any way of checking
0564:                         * register 0 if the instructions doesn't.  If it is a
0565:                         * constant instruction, deduct one from both popSpace and
0566:                         * from excessArgs, since we are popping that last argument
0567:                         * when an opc_nonnull_quick;
0568:                         */
0569:                        if (opcodeArgCount > 0 || popSpace == 0)
0570:                            return NO_INLINE_FLAG;
0571:                        popSpace--;
0572:                        excessArgs--;
0573:                        // sysAssert(excessArgs >= 0);
0574:                    }
0575:                    if (excessArgs > 2 * popSpace)
0576:                        return NO_INLINE_FLAG;
0577:                    for (i = 0; i < popSpace; i++) {
0578:                        /* If excessArgs <= popSpace, the following generates excessArgs
0579:                         * "pops" followed by nops.  Otherwise, it generates 
0580:                         * excessArgs - popSpace pop2's followed by pop's.
0581:                         */
0582:                        int opcodeTmp = (excessArgs <= i) ? opc_nop
0583:                                : (excessArgs <= popSpace + i) ? opc_pop
0584:                                        : opc_pop2;
0585:                        result |= (opcodeTmp << (i << 3));
0586:                    }
0587:                    if (checkThis)
0588:                        result |= opc_nonnull_quick << ((i++) << 3);
0589:                    // sysAssert(i + icount == 3);
0590:                    switch (icount) {
0591:                    case 3:
0592:                        result |= op2 << ((i + 2) << 3);
0593:                    case 2:
0594:                        result |= op1 << ((i + 1) << 3);
0595:                    case 1:
0596:                        result |= opcode << ((i + 0) << 3);
0597:                    }
0598:                    return result;
0599:                }
0600:            }
0601:
0602:            /* 
0603:             * Called by makeOpcodeResult.  
0604:             * Same arguments.  But there are extra arguments on the bottom to pop.
0605:             */
0606:            private int makePoppingResult(boolean checkThis, int firstReg,
0607:                    int opcodeArgCount, int icount, int opcode, int op1, int op2) {
0608:                MethodInfo mb = method;
0609:                int argsSize = mb.argsSize;
0610:                int excessArgs = argsSize - opcodeArgCount - firstReg; /* extra on top*/
0611:
0612:                if (icount > 1)
0613:                    /* We're just not prepared to deal with this. */
0614:                    return NO_INLINE_FLAG;
0615:
0616:                if (OpcodeInfo[opcode].outStack == 0) {
0617:                    int result = 0;
0618:                    /* Something like an array store, that leaves no value on the
0619:                           stack */
0620:                    int i = 0;
0621:                    /* We can't deal with checkThis, since it might reverse the order of
0622:                     * an exception.  We have a total of two instructions to do all the 
0623:                     * pre and post popping.
0624:                     */
0625:                    if (checkThis
0626:                            || ((excessArgs + 1) / 2 + (firstReg + 1) / 2) > 2)
0627:                        return NO_INLINE_FLAG;
0628:                    for (; excessArgs > 0; excessArgs -= 2)
0629:                        /* pre popping */
0630:                        result |= (excessArgs == 1 ? opc_pop : opc_pop2) << ((i++) << 3);
0631:                    result |= opcode << ((i++) << 3);
0632:                    for (; firstReg > 0; firstReg -= 2)
0633:                        /* post popping */
0634:                        result |= (firstReg == 1 ? opc_pop : opc_pop2) << ((i++) << 3);
0635:                    while (i < 3)
0636:                        result |= opc_nop << ((i++) << 3);
0637:                    return result;
0638:                }
0639:
0640:                if (excessArgs > 0 || firstReg > 1)
0641:                    /* We can't both do useful work and remove more than this many 
0642:                     * items from the stack. */
0643:                    return NO_INLINE_FLAG;
0644:
0645:                if (opcodeArgCount == 1) {
0646:                    return MAKE_INLINING(opc_swap,
0647:                            checkThis ? opc_nonnull_quick : opc_pop, opcode);
0648:                }
0649:                if (((OpcodeInfo[opcode].flags & (OpcodeInfoType.NULL_CHECK | OpcodeInfoType.CAN_ERROR)) == 0)
0650:                        && (OpcodeInfo[opcode].outStack == 1)) {
0651:                    /* The result creates one thing on the stack, and it can't error */
0652:                    return MAKE_INLINING(opcode, opc_swap,
0653:                            checkThis ? opc_nonnull_quick : opc_pop);
0654:                }
0655:                return NO_INLINE_FLAG;
0656:            }
0657:
0658:            private static boolean isXreturn(int opcode) {
0659:                return (opcode >= opc_ireturn) && (opcode <= opc_areturn);
0660:            }
0661:
0662:            private static byte INLINING_WORD1(int simp) {
0663:                return (byte) (simp & 0xFF);
0664:            }
0665:
0666:            private static byte INLINING_WORD2(int simp) {
0667:                return (byte) ((simp >> 8) & 0xFF);
0668:            }
0669:
0670:            private static byte INLINING_WORD3(int simp) {
0671:                return (byte) ((simp >> 16) & 0xFF);
0672:            }
0673:
0674:            private static int MAKE_INLINING(int op1, int op2, int op3) {
0675:                return (op1 << 0) + (op2 << 8) + (op3 << 16);
0676:            }
0677:
0678:            private static int REGSIZE(OpcodeInfoType ptr) {
0679:                return (ptr.inStack);
0680:            }
0681:
0682:            private static int REGNUM(OpcodeInfoType ptr) {
0683:                return (ptr.outStack);
0684:            }
0685:
0686:            static OpcodeInfoType[] OpcodeInfo = {
0687:                    /*  { opc_pop  <number of words to pop from stack> } 
0688:                     *  { opc_iadd <words popped from stack> <words pushed to stack> }
0689:                     *  { opc_iload <words pushed to stack> } 
0690:                     *  { opc_iload_0 <words pushed to stack> <implicit register> } 
0691:                     *  { opc_return  <words returned> } 
0692:                     *    255 indicates opcode that we can't inline
0693:                     *  other values are special opcodes that must be handled specially
0694:                     */
0695:
0696:                    /* nop               */new OpcodeInfoType(opc_pop, 0),
0697:                    /* aconst_null       */new OpcodeInfoType(opc_iadd, 0, 1),
0698:                    /* iconst_m1         */new OpcodeInfoType(opc_iadd, 0, 1),
0699:                    /* iconst_0          */new OpcodeInfoType(opc_iadd, 0, 1),
0700:                    /* iconst_1          */new OpcodeInfoType(opc_iadd, 0, 1),
0701:                    /* iconst_2          */new OpcodeInfoType(opc_iadd, 0, 1),
0702:                    /* iconst_3          */new OpcodeInfoType(opc_iadd, 0, 1),
0703:                    /* iconst_4          */new OpcodeInfoType(opc_iadd, 0, 1),
0704:                    /* iconst_5          */new OpcodeInfoType(opc_iadd, 0, 1),
0705:                    /* lconst_0          */new OpcodeInfoType(opc_iadd, 0, 2),
0706:                    /* lconst_1          */new OpcodeInfoType(opc_iadd, 0, 2),
0707:                    /* fconst_0          */new OpcodeInfoType(opc_iadd, 0, 1),
0708:                    /* fconst_1          */new OpcodeInfoType(opc_iadd, 0, 1),
0709:                    /* fconst_2          */new OpcodeInfoType(opc_iadd, 0, 1),
0710:                    /* dconst_0          */new OpcodeInfoType(opc_iadd, 0, 2),
0711:                    /* dconst_1          */new OpcodeInfoType(opc_iadd, 0, 2),
0712:                    /* bipush            */new OpcodeInfoType(opc_iadd, 0, 1),
0713:                    /* sipush            */new OpcodeInfoType(opc_iadd, 0, 1),
0714:                    /* ldc               */new OpcodeInfoType(255),
0715:                    /* ldc_w             */new OpcodeInfoType(255),
0716:                    /* ldc2_w            */new OpcodeInfoType(255),
0717:                    /* iload             */new OpcodeInfoType(opc_iload, 1),
0718:                    /* lload             */new OpcodeInfoType(opc_iload, 2),
0719:                    /* fload             */new OpcodeInfoType(opc_iload, 1),
0720:                    /* dload             */new OpcodeInfoType(opc_iload, 2),
0721:                    /* aload             */new OpcodeInfoType(opc_iload, 1),
0722:                    /* iload_0           */new OpcodeInfoType(opc_iload_0, 1,
0723:                            0),
0724:                    /* iload_1           */new OpcodeInfoType(opc_iload_0, 1,
0725:                            1),
0726:                    /* iload_2           */new OpcodeInfoType(opc_iload_0, 1,
0727:                            2),
0728:                    /* iload_3           */new OpcodeInfoType(opc_iload_0, 1,
0729:                            3),
0730:                    /* lload_0           */new OpcodeInfoType(opc_iload_0, 2,
0731:                            0),
0732:                    /* lload_1           */new OpcodeInfoType(opc_iload_0, 2,
0733:                            1),
0734:                    /* lload_2           */new OpcodeInfoType(opc_iload_0, 2,
0735:                            2),
0736:                    /* lload_3           */new OpcodeInfoType(opc_iload_0, 2,
0737:                            3),
0738:                    /* fload_0           */new OpcodeInfoType(opc_iload_0, 1,
0739:                            0),
0740:                    /* fload_1           */new OpcodeInfoType(opc_iload_0, 1,
0741:                            1),
0742:                    /* fload_2           */new OpcodeInfoType(opc_iload_0, 1,
0743:                            2),
0744:                    /* fload_3           */new OpcodeInfoType(opc_iload_0, 1,
0745:                            3),
0746:                    /* dload_0           */new OpcodeInfoType(opc_iload_0, 2,
0747:                            0),
0748:                    /* dload_1           */new OpcodeInfoType(opc_iload_0, 2,
0749:                            1),
0750:                    /* dload_2           */new OpcodeInfoType(opc_iload_0, 2,
0751:                            2),
0752:                    /* dload_3           */new OpcodeInfoType(opc_iload_0, 2,
0753:                            3),
0754:                    /* aload_0           */new OpcodeInfoType(opc_iload_0, 1,
0755:                            0),
0756:                    /* aload_1           */new OpcodeInfoType(opc_iload_0, 1,
0757:                            1),
0758:                    /* aload_2           */new OpcodeInfoType(opc_iload_0, 1,
0759:                            2),
0760:                    /* aload_3           */new OpcodeInfoType(opc_iload_0, 1,
0761:                            3),
0762:                    /* iaload            */new OpcodeInfoType(opc_iadd, 2, 1,
0763:                            OpcodeInfoType.NULL_CHECK),
0764:                    /* laload            */new OpcodeInfoType(opc_iadd, 2, 2,
0765:                            OpcodeInfoType.NULL_CHECK),
0766:                    /* faload            */new OpcodeInfoType(opc_iadd, 2, 1,
0767:                            OpcodeInfoType.NULL_CHECK),
0768:                    /* daload            */new OpcodeInfoType(opc_iadd, 2, 2,
0769:                            OpcodeInfoType.NULL_CHECK),
0770:                    /* aaload            */new OpcodeInfoType(opc_iadd, 2, 1,
0771:                            OpcodeInfoType.NULL_CHECK),
0772:                    /* baload            */new OpcodeInfoType(opc_iadd, 2, 1,
0773:                            OpcodeInfoType.NULL_CHECK),
0774:                    /* caload            */new OpcodeInfoType(opc_iadd, 2, 1,
0775:                            OpcodeInfoType.NULL_CHECK),
0776:                    /* saload            */new OpcodeInfoType(opc_iadd, 2, 1,
0777:                            OpcodeInfoType.NULL_CHECK),
0778:                    /* istore            */new OpcodeInfoType(255),
0779:                    /* lstore            */new OpcodeInfoType(255),
0780:                    /* fstore            */new OpcodeInfoType(255),
0781:                    /* dstore            */new OpcodeInfoType(255),
0782:                    /* astore            */new OpcodeInfoType(255),
0783:                    /* istore_0          */new OpcodeInfoType(255),
0784:                    /* istore_1          */new OpcodeInfoType(255),
0785:                    /* istore_2          */new OpcodeInfoType(255),
0786:                    /* istore_3          */new OpcodeInfoType(255),
0787:                    /* lstore_0          */new OpcodeInfoType(255),
0788:                    /* lstore_1          */new OpcodeInfoType(255),
0789:                    /* lstore_2          */new OpcodeInfoType(255),
0790:                    /* lstore_3          */new OpcodeInfoType(255),
0791:                    /* fstore_0          */new OpcodeInfoType(255),
0792:                    /* fstore_1          */new OpcodeInfoType(255),
0793:                    /* fstore_2          */new OpcodeInfoType(255),
0794:                    /* fstore_3          */new OpcodeInfoType(255),
0795:                    /* dstore_0          */new OpcodeInfoType(255),
0796:                    /* dstore_1          */new OpcodeInfoType(255),
0797:                    /* dstore_2          */new OpcodeInfoType(255),
0798:                    /* dstore_3          */new OpcodeInfoType(255),
0799:                    /* astore_0          */new OpcodeInfoType(255),
0800:                    /* astore_1          */new OpcodeInfoType(255),
0801:                    /* astore_2          */new OpcodeInfoType(255),
0802:                    /* astore_3          */new OpcodeInfoType(255),
0803:                    /* iastore           */new OpcodeInfoType(opc_iadd, 3, 0,
0804:                            OpcodeInfoType.NULL_CHECK),
0805:                    /* lastore           */new OpcodeInfoType(opc_iadd, 4, 0,
0806:                            OpcodeInfoType.NULL_CHECK),
0807:                    /* fastore           */new OpcodeInfoType(opc_iadd, 3, 0,
0808:                            OpcodeInfoType.NULL_CHECK),
0809:                    /* dastore           */new OpcodeInfoType(opc_iadd, 4, 0,
0810:                            OpcodeInfoType.NULL_CHECK),
0811:                    /* aastore           */new OpcodeInfoType(opc_iadd, 3, 0,
0812:                            OpcodeInfoType.NULL_CHECK),
0813:                    /* bastore           */new OpcodeInfoType(opc_iadd, 3, 0,
0814:                            OpcodeInfoType.NULL_CHECK),
0815:                    /* castore           */new OpcodeInfoType(opc_iadd, 3, 0,
0816:                            OpcodeInfoType.NULL_CHECK),
0817:                    /* sastore           */new OpcodeInfoType(opc_iadd, 3, 0,
0818:                            OpcodeInfoType.NULL_CHECK),
0819:                    /* pop               */new OpcodeInfoType(opc_pop, 1),
0820:                    /* pop2              */new OpcodeInfoType(opc_pop, 2),
0821:                    /* dup               */new OpcodeInfoType(255),
0822:                    /* dup_x1            */new OpcodeInfoType(255),
0823:                    /* dup_x2            */new OpcodeInfoType(255),
0824:                    /* dup2              */new OpcodeInfoType(255),
0825:                    /* dup2_x1           */new OpcodeInfoType(255),
0826:                    /* dup2_x2           */new OpcodeInfoType(255),
0827:                    /* swap              */new OpcodeInfoType(255),
0828:                    /* iadd              */new OpcodeInfoType(opc_iadd, 2, 1),
0829:                    /* ladd              */new OpcodeInfoType(opc_iadd, 4, 2),
0830:                    /* fadd              */new OpcodeInfoType(opc_iadd, 2, 1),
0831:                    /* dadd              */new OpcodeInfoType(opc_iadd, 4, 2),
0832:                    /* isub              */new OpcodeInfoType(opc_iadd, 2, 1),
0833:                    /* lsub              */new OpcodeInfoType(opc_iadd, 4, 2),
0834:                    /* fsub              */new OpcodeInfoType(opc_iadd, 2, 1),
0835:                    /* dsub              */new OpcodeInfoType(opc_iadd, 4, 2),
0836:                    /* imul              */new OpcodeInfoType(opc_iadd, 2, 1),
0837:                    /* lmul              */new OpcodeInfoType(opc_iadd, 4, 2),
0838:                    /* fmul              */new OpcodeInfoType(opc_iadd, 2, 1),
0839:                    /* dmul              */new OpcodeInfoType(opc_iadd, 4, 2),
0840:                    /* idiv              */new OpcodeInfoType(opc_iadd, 2, 1,
0841:                            OpcodeInfoType.CAN_ERROR),
0842:                    /* ldiv              */new OpcodeInfoType(opc_iadd, 4, 2,
0843:                            OpcodeInfoType.CAN_ERROR),
0844:                    /* fdiv              */new OpcodeInfoType(opc_iadd, 2, 1),
0845:                    /* ddiv              */new OpcodeInfoType(opc_iadd, 4, 2),
0846:                    /* irem              */new OpcodeInfoType(opc_iadd, 2, 1,
0847:                            OpcodeInfoType.CAN_ERROR),
0848:                    /* lrem              */new OpcodeInfoType(opc_iadd, 4, 2,
0849:                            OpcodeInfoType.CAN_ERROR),
0850:                    /* frem              */new OpcodeInfoType(opc_iadd, 2, 1),
0851:                    /* drem              */new OpcodeInfoType(opc_iadd, 4, 2),
0852:                    /* ineg              */new OpcodeInfoType(opc_iadd, 1, 1),
0853:                    /* lneg              */new OpcodeInfoType(opc_iadd, 2, 2),
0854:                    /* fneg              */new OpcodeInfoType(opc_iadd, 1, 1),
0855:                    /* dneg              */new OpcodeInfoType(opc_iadd, 2, 2),
0856:                    /* ishl              */new OpcodeInfoType(opc_iadd, 2, 1),
0857:                    /* lshl              */new OpcodeInfoType(opc_iadd, 3, 2),
0858:                    /* ishr              */new OpcodeInfoType(opc_iadd, 2, 1),
0859:                    /* lshr              */new OpcodeInfoType(opc_iadd, 3, 2),
0860:                    /* iushr             */new OpcodeInfoType(opc_iadd, 2, 1),
0861:                    /* lushr             */new OpcodeInfoType(opc_iadd, 3, 2),
0862:                    /* iand              */new OpcodeInfoType(opc_iadd, 2, 1),
0863:                    /* land              */new OpcodeInfoType(opc_iadd, 4, 2),
0864:                    /* ior               */new OpcodeInfoType(opc_iadd, 2, 1),
0865:                    /* lor               */new OpcodeInfoType(opc_iadd, 4, 2),
0866:                    /* ixor              */new OpcodeInfoType(opc_iadd, 2, 1),
0867:                    /* lxor              */new OpcodeInfoType(opc_iadd, 4, 2),
0868:                    /* iinc              */new OpcodeInfoType(255),
0869:                    /* i2l               */new OpcodeInfoType(opc_iadd, 1, 2),
0870:                    /* i2f               */new OpcodeInfoType(opc_iadd, 1, 1),
0871:                    /* i2d               */new OpcodeInfoType(opc_iadd, 1, 2),
0872:                    /* l2i               */new OpcodeInfoType(opc_iadd, 2, 1),
0873:                    /* l2f               */new OpcodeInfoType(opc_iadd, 2, 1),
0874:                    /* l2d               */new OpcodeInfoType(opc_iadd, 2, 2),
0875:                    /* f2i               */new OpcodeInfoType(opc_iadd, 1, 1),
0876:                    /* f2l               */new OpcodeInfoType(opc_iadd, 1, 2),
0877:                    /* f2d               */new OpcodeInfoType(opc_iadd, 1, 2),
0878:                    /* d2i               */new OpcodeInfoType(opc_iadd, 2, 1),
0879:                    /* d2l               */new OpcodeInfoType(opc_iadd, 2, 2),
0880:                    /* d2f               */new OpcodeInfoType(opc_iadd, 2, 1),
0881:                    /* i2b               */new OpcodeInfoType(opc_iadd, 1, 1),
0882:                    /* i2c               */new OpcodeInfoType(opc_iadd, 1, 1),
0883:                    /* i2s               */new OpcodeInfoType(opc_iadd, 1, 1),
0884:                    /* lcmp              */new OpcodeInfoType(opc_iadd, 4, 1),
0885:                    /* fcmpl             */new OpcodeInfoType(opc_iadd, 2, 1),
0886:                    /* fcmpg             */new OpcodeInfoType(opc_iadd, 2, 1),
0887:                    /* dcmpl             */new OpcodeInfoType(opc_iadd, 4, 1),
0888:                    /* dcmpg             */new OpcodeInfoType(opc_iadd, 4, 1),
0889:                    /* ifeq              */new OpcodeInfoType(255),
0890:                    /* ifne              */new OpcodeInfoType(255),
0891:                    /* iflt              */new OpcodeInfoType(255),
0892:                    /* ifge              */new OpcodeInfoType(255),
0893:                    /* ifgt              */new OpcodeInfoType(255),
0894:                    /* ifle              */new OpcodeInfoType(255),
0895:                    /* if_icmpeq         */new OpcodeInfoType(255),
0896:                    /* if_icmpne         */new OpcodeInfoType(255),
0897:                    /* if_icmplt         */new OpcodeInfoType(255),
0898:                    /* if_icmpge         */new OpcodeInfoType(255),
0899:                    /* if_icmpgt         */new OpcodeInfoType(255),
0900:                    /* if_icmple         */new OpcodeInfoType(255),
0901:                    /* if_acmpeq         */new OpcodeInfoType(255),
0902:                    /* if_acmpne         */new OpcodeInfoType(255),
0903:                    /* goto              */new OpcodeInfoType(255),
0904:                    /* jsr               */new OpcodeInfoType(255),
0905:                    /* ret               */new OpcodeInfoType(255),
0906:                    /* tableswitch       */new OpcodeInfoType(255),
0907:                    /* lookupswitch      */new OpcodeInfoType(255),
0908:                    /* ireturn           */new OpcodeInfoType(opc_return, 1),
0909:                    /* lreturn           */new OpcodeInfoType(opc_return, 2),
0910:                    /* freturn           */new OpcodeInfoType(opc_return, 1),
0911:                    /* dreturn           */new OpcodeInfoType(opc_return, 2),
0912:                    /* areturn           */new OpcodeInfoType(opc_return, 1),
0913:                    /* return            */new OpcodeInfoType(opc_return, 0),
0914:                    /* getstatic         */new OpcodeInfoType(255),
0915:                    /* putstatic         */new OpcodeInfoType(255),
0916:                    /* getfield          */new OpcodeInfoType(255),
0917:                    /* putfield          */new OpcodeInfoType(255),
0918:                    /* invokevirtual     */new OpcodeInfoType(255),
0919:                    /* invokespecial     */new OpcodeInfoType(255),
0920:                    /* invokestatic      */new OpcodeInfoType(255),
0921:                    /* invokeinterface   */new OpcodeInfoType(255),
0922:                    /* xxxunusedxxx      */new OpcodeInfoType(255),
0923:                    /* new               */new OpcodeInfoType(255),
0924:                    /* newarray          */new OpcodeInfoType(opc_iadd, 1, 1,
0925:                            OpcodeInfoType.CAN_ERROR),
0926:                    /* anewarray         */new OpcodeInfoType(255),
0927:                    /* arraylength       */new OpcodeInfoType(opc_iadd, 1, 1,
0928:                            OpcodeInfoType.NULL_CHECK),
0929:                    /* athrow            */new OpcodeInfoType(opc_iadd, 1, 0,
0930:                            OpcodeInfoType.NULL_CHECK
0931:                                    | OpcodeInfoType.CAN_ERROR),
0932:                    /* checkcast         */new OpcodeInfoType(255),
0933:                    /* instanceof        */new OpcodeInfoType(255),
0934:                    /* monitorenter      */new OpcodeInfoType(opc_iadd, 1, 0,
0935:                            OpcodeInfoType.NULL_CHECK
0936:                                    | OpcodeInfoType.CAN_ERROR),
0937:                    /* monitorexit       */new OpcodeInfoType(opc_iadd, 1, 0,
0938:                            OpcodeInfoType.NULL_CHECK
0939:                                    | OpcodeInfoType.CAN_ERROR),
0940:                    /* wide              */new OpcodeInfoType(255),
0941:                    /* multianewarray    */new OpcodeInfoType(255),
0942:                    /* ifnull            */new OpcodeInfoType(255),
0943:                    /* ifnonnull         */new OpcodeInfoType(255),
0944:                    /* goto_w            */new OpcodeInfoType(255),
0945:                    /* jsr_w             */new OpcodeInfoType(255),
0946:                    /* breakpoint        */new OpcodeInfoType(255)
0947:
0948:            /* IMPL_NOTE:  I still need to add more info here */
0949:
0950:            };
0951:
0952:            /**
0953:             * Print the code as Java assembly language instructions
0954:             */
0955:            String disassembleInlining() {
0956:                byte codeBytes[] = new byte[3];
0957:                // Copy inlining into codeBytes[] buffer
0958:                codeBytes[0] = (byte) (inlining & 0xff);
0959:                codeBytes[1] = (byte) ((inlining >> 8) & 0xff);
0960:                codeBytes[2] = (byte) ((inlining >> 16) & 0xff);
0961:                return MethodInfo.disassemble(codeBytes, 0, 3);
0962:            }
0963:
0964:            private String myName;
0965:
0966:            public String toString() {
0967:                if (myName == null) {
0968:                    myName = method.parent.className + "." + method.name.string
0969:                            + method.type.string;
0970:                }
0971:                return myName;
0972:            }
0973:
0974:            static int total = 0;
0975:
0976:            // After inlining some code, we try to see if we can remove code.  For
0977:            // example, the frequent case of opc_aload_0 invokeingored_quick #1 T can
0978:            // simply "go away"
0979:
0980:            final boolean compress() {
0981:                MethodInfo mb = method;
0982:                boolean rewritten = false;
0983:                byte[] code = mb.code;
0984:                int[] stack = new int[mb.stack + 1];
0985:                int stackHeight = 0;
0986:                int nextpc;
0987:                java.util.BitSet targets = mb.getLabelTargets();
0988:
0989:                for (int pc = 0; pc < code.length; pc = nextpc) {
0990:                    nextpc = pc + mb.opcodeLength(pc);
0991:                    int opcode = code[pc] & 0xff;
0992:                    int popping = 0;
0993:                    boolean checkThis = false;
0994:
0995:                    if (targets.get(pc)) {
0996:                        stackHeight = 0;
0997:                    }
0998:                    stack[stackHeight] = pc;
0999:
1000:                    // Invariant.  the stackheight at this point is stackHeight or less.
1001:                    // 
1002:                    // We can pop n items from the stack (where n <= stackHeight) by
1003:                    // simply deleting all the code from stackHeight[n] to this point
1004:                    // in the code.  No side effects are removed.
1005:                    // 
1006:                    // Note that instructions that have a side effect should set
1007:                    // stackHeight = 0, to indicate that it can't be deleted.
1008:
1009:                    switch (opcode) {
1010:                    case opc_nop:
1011:                    case opc_ineg:
1012:                    case opc_fneg:
1013:                    case opc_i2f:
1014:                    case opc_f2i:
1015:                    case opc_i2b:
1016:                    case opc_i2c:
1017:                    case opc_i2s:
1018:                    case opc_newarray:
1019:                    case opc_anewarray_fast:
1020:                    case opc_instanceof _fast:
1021:                    case opc_lneg:
1022:                    case opc_dneg:
1023:                    case opc_l2d:
1024:                    case opc_d2l:
1025:                        // these don't change stack height, and we know as much about
1026:                        // the stack before as we do after.
1027:                        break;
1028:
1029:                    case opc_aconst_null:
1030:                    case opc_iconst_m1:
1031:                    case opc_iconst_0:
1032:                    case opc_iconst_1:
1033:                    case opc_iconst_2:
1034:                    case opc_iconst_3:
1035:                    case opc_iconst_4:
1036:                    case opc_iconst_5:
1037:                    case opc_fconst_0:
1038:                    case opc_fconst_1:
1039:                    case opc_fconst_2:
1040:                    case opc_bipush:
1041:                    case opc_sipush:
1042:                    case opc_iload:
1043:                    case opc_fload:
1044:                    case opc_aload:
1045:                    case opc_iload_0:
1046:                    case opc_iload_1:
1047:                    case opc_iload_2:
1048:                    case opc_iload_3:
1049:                    case opc_fload_0:
1050:                    case opc_fload_1:
1051:                    case opc_fload_2:
1052:                    case opc_fload_3:
1053:                    case opc_aload_0:
1054:                    case opc_aload_1:
1055:                    case opc_aload_2:
1056:                    case opc_aload_3:
1057:                    case opc_getstatic_fast:
1058:                    case opc_dup:
1059:                        // These push some value onto the stack, no matter what was
1060:                        // there before
1061:                        stackHeight += 1;
1062:                        break;
1063:
1064:                    case opc_lconst_0:
1065:                    case opc_lconst_1:
1066:                    case opc_dconst_0:
1067:                    case opc_dconst_1:
1068:                    case opc_lload:
1069:                    case opc_dload:
1070:                    case opc_lload_0:
1071:                    case opc_lload_1:
1072:                    case opc_lload_2:
1073:                    case opc_lload_3:
1074:                    case opc_dload_0:
1075:                    case opc_dload_1:
1076:                    case opc_dload_2:
1077:                    case opc_dload_3:
1078:                    case opc_getstatic2_fast:
1079:                        // These push two values onto the stack, no matter what was 
1080:                        // there before.
1081:                        stackHeight += 2;
1082:                        break;
1083:
1084:                    case opc_i2l:
1085:                    case opc_i2d:
1086:                    case opc_f2l:
1087:                    case opc_f2d:
1088:                        // if we knew the top element of the stack, we know more
1089:                        stackHeight = (stackHeight < 1) ? 0 : stackHeight + 1;
1090:                        break;
1091:
1092:                    case opc_iadd:
1093:                    case opc_fadd:
1094:                    case opc_isub:
1095:                    case opc_fsub:
1096:                    case opc_imul:
1097:                    case opc_fmul:
1098:                    case opc_fdiv:
1099:                    case opc_frem:
1100:                    case opc_ishl:
1101:                    case opc_ishr:
1102:                    case opc_iushr:
1103:                    case opc_iand:
1104:                    case opc_ior:
1105:                    case opc_ixor:
1106:                    case opc_l2i:
1107:                    case opc_l2f:
1108:                    case opc_d2i:
1109:                    case opc_d2f:
1110:                    case opc_fcmpl:
1111:                    case opc_fcmpg:
1112:                        // if we knew the top two elements of the stack, the stack
1113:                        // has just shrunk
1114:                        stackHeight = (stackHeight < 2) ? 0 : stackHeight - 1;
1115:                        break;
1116:
1117:                    case opc_lshl:
1118:                    case opc_lshr:
1119:                    case opc_lushr:
1120:                        // if we knew the top three elements of the stack, we now
1121:                        // know the top two
1122:                        stackHeight = (stackHeight < 3) ? 0 : stackHeight - 1;
1123:                        break;
1124:
1125:                    case opc_lcmp:
1126:                    case opc_dcmpl:
1127:                    case opc_dcmpg:
1128:                        // if we knew the top 4 elements of the stack, we now
1129:                        // know the top element
1130:                        stackHeight = (stackHeight < 4) ? 0 : stackHeight - 3;
1131:                        break;
1132:
1133:                    case opc_ladd:
1134:                    case opc_dadd:
1135:                    case opc_lsub:
1136:                    case opc_dsub:
1137:                    case opc_lmul:
1138:                    case opc_dmul:
1139:                    case opc_ddiv:
1140:                    case opc_drem:
1141:                    case opc_land:
1142:                    case opc_lor:
1143:                    case opc_lxor:
1144:                        // if we knew the top 4 elements of the stack, we now
1145:                        // know the top 2
1146:                        stackHeight = (stackHeight < 4) ? 0 : stackHeight - 2;
1147:                        break;
1148:
1149:                    // The dup's (other than opc_dup) deal with the stack in 
1150:                    // a way that's not worth the hassle of dealing with.
1151:
1152:                    case opc_getfield_fast:
1153:                    case opc_arraylength:
1154:                        // If we throw away the result, then we just need to check that
1155:                        // the value is non-null.
1156:                        if (code[nextpc] == (byte) (opc_pop)) {
1157:                            checkThis = true;
1158:                            nextpc += 1;
1159:                        } else {
1160:                            stackHeight = 0;
1161:                        }
1162:                        break;
1163:
1164:                    case opc_pop2:
1165:                        popping++; // fall thru
1166:                    case opc_pop:
1167:                        // We have to be careful.  The inliner may produce code that
1168:                        // does correspond to the stack.  For example, it might 
1169:                        // produce "pop pop2" to remove a double then an int.  We need
1170:                        // to deal with series of them at once.
1171:                        if (stackHeight > 0) {
1172:                            popping++;
1173:                            for (;;) {
1174:                                opcode = code[++pc] & 0xFF;
1175:                                if (opcode == opc_pop)
1176:                                    popping++;
1177:                                else if (opcode == opc_pop2)
1178:                                    popping += 2;
1179:                                else
1180:                                    break;
1181:                            }
1182:                            nextpc = pc;
1183:                        }
1184:                        break;
1185:
1186:                    case opc_invokeignored_quick:
1187:                        popping = code[pc + 1] & 0xff;
1188:                        if (code[pc + 2] != 0) {
1189:                            checkThis = true;
1190:                            popping--;
1191:                        }
1192:                        break;
1193:
1194:                    default:
1195:                        stackHeight = 0;
1196:                    }
1197:
1198:                    if (checkThis || (popping > 0 && stackHeight > 0)) {
1199:                        rewritten = true;
1200:                        if (stackHeight >= popping) {
1201:                            stackHeight -= popping;
1202:                            popping = 0;
1203:                        } else {
1204:                            popping -= stackHeight;
1205:                            stackHeight = 0;
1206:                        }
1207:                        int start = stack[stackHeight];
1208:
1209:                        if (checkThis) {
1210:                            if (popping == 0 && (nextpc - start != 3)) {
1211:                                mb
1212:                                        .replaceCode(start, nextpc,
1213:                                                opc_nonnull_quick);
1214:                            } else {
1215:                                mb
1216:                                        .replaceCode(start, nextpc,
1217:                                                opc_invokeignored_quick,
1218:                                                popping + 1, 1);
1219:                            }
1220:                            stackHeight = 0;
1221:                        } else {
1222:                            switch (popping) {
1223:                            case 0:
1224:                                mb.replaceCode(start, nextpc);
1225:                                break;
1226:                            case 1:
1227:                                mb.replaceCode(start, nextpc, opc_pop);
1228:                                break;
1229:                            case 2:
1230:                                mb.replaceCode(start, nextpc, opc_pop2);
1231:                                break;
1232:                            default:
1233:                                mb.replaceCode(start, nextpc,
1234:                                        opc_invokeignored_quick, popping, 0);
1235:                                break;
1236:                            }
1237:                        }
1238:                    }
1239:                }
1240:                return rewritten;
1241:            }
1242:        }
1243:
1244:        /**
1245:         * Class used for inlining info.  See inlining code in MethodInfo
1246:         */
1247:        class OpcodeInfoType {
1248:            int opcode; // really the opcode type
1249:            int inStack;
1250:            int outStack;
1251:
1252:            static final int CAN_ERROR = 0x01; /* can give error in addition to
1253:            				   NULL_CHECK */
1254:            static final int NULL_CHECK = 0x02; /* checks that first arg isn't null */
1255:            static final int CONSTANT_POOL = 0x04; /* uses the constant pool */
1256:            int flags;
1257:
1258:            OpcodeInfoType(int opcode, int inStack, int outStack, int flags) {
1259:                this .opcode = opcode;
1260:                this .inStack = inStack;
1261:                this .outStack = outStack;
1262:                this .flags = flags;
1263:            }
1264:
1265:            OpcodeInfoType(int opcode, int inStack, int outStack) {
1266:                this (opcode, inStack, outStack, 0);
1267:            }
1268:
1269:            OpcodeInfoType(int opcode, int inStack) {
1270:                this (opcode, inStack, 0, 0);
1271:            }
1272:
1273:            OpcodeInfoType(int opcode) {
1274:                this (opcode, 0, 0, 0);
1275:            }
1276:        };
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.