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