Source Code Cross Referenced for CodeAttr.java in  » Scripting » Nice » gnu » bytecode » 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 » Scripting » Nice » gnu.bytecode 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        // Copyright (c) 1997, 1998, 1999, 2001  Per M.A. Bothner.
0002:        // This is free software;  for terms and warranty disclaimer see ./COPYING.
0003:
0004:        package gnu.bytecode;
0005:
0006:        import java.io.*;
0007:
0008:        /**
0009:         * Represents the contents of a standard "Code" attribute.
0010:         * <p>
0011:         * Most of the actual methods that generate bytecode operation
0012:         * are in this class (typically with names starting with <code>emit</code>),
0013:         * though there are also some in <code>Method</code>.
0014:         * <p>
0015:         * Note that a <code>CodeAttr</code> is an <code>Attribute</code>
0016:         * of a <code>Method</code>, and can in turn contain other
0017:         * <code>Attribute</code>s, such as a <code>LineNumbersAttr</code>.
0018:         *
0019:         * @author      Per Bothner
0020:         */
0021:
0022:        public class CodeAttr extends Attribute implements  AttrContainer {
0023:            Attribute attributes;
0024:
0025:            public final Attribute getAttributes() {
0026:                return attributes;
0027:            }
0028:
0029:            public final void setAttributes(Attribute attributes) {
0030:                this .attributes = attributes;
0031:            }
0032:
0033:            LineNumbersAttr lines;
0034:            public LocalVarsAttr locals;
0035:
0036:            // In hindsight, maintaining stack_types is more hassle than it is worth.
0037:            // Instead, better to just keep track of SP, which should catch most
0038:            // stack errors, while being more general and less hassle.  FIXME.
0039:            Type[] stack_types;
0040:
0041:            public int SP; // Current stack size (in "words")
0042:            private int max_stack;
0043:            private int max_locals;
0044:            int PC;
0045:            // readPC (which is <= PC) is a bound on locations that have been
0046:            // saved into labels or otherwise externally seen.
0047:            // Hence, we cannot re-arrange code upto readPC, but we can
0048:            // rearrange code between readPC and PC.
0049:            int readPC;
0050:            byte[] code;
0051:
0052:            // The PC of the previous instruction.
0053:            int previousPC;
0054:
0055:            /* The exception handler table, as a vector of quadruples
0056:               (start_pc, end_pc, handler_pc, catch_type).
0057:               Only the first exception_table_length quadrules are defined. */
0058:            short[] exception_table;
0059:
0060:            /* The number of (defined) exception handlers (i.e. quadruples)
0061:               in exception_table. */
0062:            int exception_table_length;
0063:
0064:            /* A chain of labels.  Unsorted, except that the Label with
0065:               the lowest element in fixups must be the first one. */
0066:            Label labels;
0067:
0068:            CodeFragment fragments;
0069:
0070:            /** The stack of currently active conditionals. */
0071:            IfState if_stack;
0072:
0073:            /** The stack of currently active try statements. */
0074:            TryState try_stack;
0075:
0076:            public final TryState getTryStack() {
0077:                return try_stack;
0078:            }
0079:
0080:            public final Method getMethod() {
0081:                return (Method) getContainer();
0082:            }
0083:
0084:            public final int getPC() {
0085:                return PC;
0086:            }
0087:
0088:            public final ConstantPool getConstants() {
0089:                return getMethod().classfile.constants;
0090:            }
0091:
0092:            /* True if we cannot fall through to bytes[PC] -
0093:               the previous instruction was an uncondition control transfer.  */
0094:            boolean unreachable_here;
0095:
0096:            /** True if control could reach here. */
0097:            public boolean reachableHere() {
0098:                return !unreachable_here;
0099:            }
0100:
0101:            public final void setReachable(boolean val) {
0102:                unreachable_here = !val;
0103:            }
0104:
0105:            public final void setUnreachable() {
0106:                unreachable_here = true;
0107:            }
0108:
0109:            /** Get the maximum number of words on the operand stack in this method. */
0110:            public int getMaxStack() {
0111:                return max_stack;
0112:            }
0113:
0114:            /** Get the maximum number of local variable words in this method. */
0115:            public int getMaxLocals() {
0116:                return max_locals;
0117:            }
0118:
0119:            /** Set the maximum number of words on the operand stack in this method. */
0120:            public void setMaxStack(int n) {
0121:                max_stack = n;
0122:            }
0123:
0124:            /** Set the maximum number of local variable words in this method. */
0125:            public void setMaxLocals(int n) {
0126:                max_locals = n;
0127:            }
0128:
0129:            /** Get the code (instruction bytes) of this method.
0130:             * Does not make a copy. */
0131:            public byte[] getCode() {
0132:                return code;
0133:            }
0134:
0135:            /** Set the code (instruction bytes) of this method.
0136:             * @param code the code bytes (which are not copied).
0137:             * Implicitly calls setCodeLength(code.length). */
0138:            public void setCode(byte[] code) {
0139:                this .code = code;
0140:                this .PC = code.length;
0141:                readPC = PC;
0142:            }
0143:
0144:            /** Set the length the the code (instruction bytes) of this method.
0145:             * That is the number of current used bytes in getCode().
0146:             * (Any remaing bytes provide for future growth.) */
0147:            public void setCodeLength(int len) {
0148:                PC = len;
0149:                readPC = len;
0150:            }
0151:
0152:            /** Set the current lengthof the code (instruction bytes) of this method. */
0153:            public int getCodeLength() {
0154:                readPC = PC;
0155:                return PC;
0156:            }
0157:
0158:            public CodeAttr(Method meth) {
0159:                super ("Code");
0160:                addToFrontOf(meth);
0161:                meth.code = this ;
0162:            }
0163:
0164:            public final void reserve(int bytes) {
0165:                previousPC = PC;
0166:                if (code == null)
0167:                    code = new byte[100 + bytes];
0168:                else if (PC + bytes > code.length) {
0169:                    byte[] new_code = new byte[2 * code.length + bytes];
0170:                    System.arraycopy(code, 0, new_code, 0, PC);
0171:                    code = new_code;
0172:                }
0173:
0174:                while (labels != null && labels.fixups != null) {
0175:                    int oldest_fixup = labels.fixups[0];
0176:                    int threshold = unreachable_here ? 30000 : 32000;
0177:                    if (PC + bytes - oldest_fixup > threshold)
0178:                        labels.emit_spring(this );
0179:                    else
0180:                        break;
0181:                }
0182:            }
0183:
0184:            /**
0185:             * Write an 8-bit byte to the current code-stream.
0186:             * @param i the byte to write
0187:             */
0188:            public final void put1(int i) {
0189:                code[PC++] = (byte) i;
0190:                unreachable_here = false;
0191:            }
0192:
0193:            /**
0194:             * Write a 16-bit short to the current code-stream
0195:             * @param i the value to write
0196:             */
0197:            public final void put2(int i) {
0198:                code[PC++] = (byte) (i >> 8);
0199:                code[PC++] = (byte) (i);
0200:                unreachable_here = false;
0201:            }
0202:
0203:            /**
0204:             * Write a 32-bit int to the current code-stream
0205:             * @param i the value to write
0206:             */
0207:            public final void put4(int i) {
0208:                code[PC++] = (byte) (i >> 24);
0209:                code[PC++] = (byte) (i >> 16);
0210:                code[PC++] = (byte) (i >> 8);
0211:
0212:                code[PC++] = (byte) (i);
0213:                unreachable_here = false;
0214:            }
0215:
0216:            public final void putIndex2(CpoolEntry cnst) {
0217:                put2(cnst.index);
0218:            }
0219:
0220:            public final void putLineNumber(String file, int linenumber) {
0221:                if (lines == null)
0222:                    lines = new LineNumbersAttr(this );
0223:                readPC = PC;
0224:                lines.put(file, linenumber, PC);
0225:            }
0226:
0227:            public final void pushType(Type type) {
0228:                if (type.size == 0)
0229:                    throw new Error("pushing void type onto stack");
0230:                if (stack_types == null)
0231:                    stack_types = new Type[20];
0232:                else if (SP + 1 >= stack_types.length) {
0233:                    Type[] new_array = new Type[2 * stack_types.length];
0234:                    System.arraycopy(stack_types, 0, new_array, 0, SP);
0235:                    stack_types = new_array;
0236:                }
0237:                if (type.size == 8)
0238:                    stack_types[SP++] = Type.void_type;
0239:                stack_types[SP++] = type;
0240:                if (SP > max_stack)
0241:                    max_stack = SP;
0242:            }
0243:
0244:            public final Type popType() {
0245:                if (SP <= 0)
0246:                    throw new Error("popType called with empty stack in "
0247:                            + getMethod());
0248:                Type type = stack_types[--SP];
0249:                if (type.size == 8)
0250:                    if (!popType().isVoid())
0251:                        throw new Error("missing void type on stack");
0252:                return type;
0253:            }
0254:
0255:            public final Type topType() {
0256:                if (SP <= 0)
0257:                    //throw new Error("popType called with empty stack "+getMethod());
0258:                    return null;
0259:                return stack_types[SP - 1];
0260:            }
0261:
0262:            /** Compile code to pop values off the stack (and ignore them).
0263:             * @param nvalues the number of values (not words) to pop
0264:             */
0265:            public void emitPop(int nvalues) {
0266:                for (; nvalues > 0; --nvalues) {
0267:                    reserve(1);
0268:                    Type type = popType();
0269:                    if (type.size > 4)
0270:                        put1(88); // pop2
0271:                    else if (nvalues > 1) { // optimization:  can we pop 2 4-byte words using a pop2
0272:                        Type type2 = popType();
0273:                        if (type2.size > 4) {
0274:                            put1(87); // pop
0275:                            reserve(1);
0276:                        }
0277:                        put1(88); // pop2
0278:                        --nvalues;
0279:                    } else
0280:                        put1(87); // pop
0281:                }
0282:            }
0283:
0284:            public void emitSwap() {
0285:                reserve(1);
0286:                Type type1 = popType();
0287:                Type type2 = popType();
0288:
0289:                if (type1.size > 4 || type2.size > 4) {
0290:                    // There is no swap instruction in the JVM for this case.
0291:                    // Fall back to a more convoluted way.
0292:                    pushType(type2);
0293:                    pushType(type1);
0294:                    emitDupX();
0295:                    emitPop(1);
0296:                } else {
0297:                    pushType(type1);
0298:                    put1(95); // swap
0299:                    pushType(type2);
0300:                }
0301:            }
0302:
0303:            /** Emit code to duplicate the top element of the stack. */
0304:            public void emitDup() {
0305:                reserve(1);
0306:
0307:                Type type = topType();
0308:                put1(type.size <= 4 ? 89 : 92); // dup or dup2
0309:                pushType(type);
0310:            }
0311:
0312:            public void emitNop() {
0313:                reserve(1);
0314:                put1(0); // nop
0315:            }
0316:
0317:            /** Emit code to duplicate the top element of the stack
0318:                and place the copy before the previous element. */
0319:            public void emitDupX() {
0320:                reserve(1);
0321:
0322:                Type type = popType();
0323:                Type skipedType = popType();
0324:
0325:                if (skipedType.size <= 4)
0326:                    put1(type.size <= 4 ? 90 : 93); // dup_x1 or dup2_x1
0327:                else
0328:                    put1(type.size <= 4 ? 91 : 94); // dup_x2 or dup2_x2
0329:
0330:                pushType(type);
0331:                pushType(skipedType);
0332:                pushType(type);
0333:            }
0334:
0335:            /** Compile code to duplicate with offset.
0336:             * @param size the size of the stack item to duplicate (1 or 2)
0337:             * @param offset where to insert the result (must be 0, 1, or 2)
0338:             * The new words get inserted at stack[SP-size-offset]
0339:             */
0340:            public void emitDup(int size, int offset) {
0341:                if (size == 0)
0342:                    return;
0343:                reserve(1);
0344:                // copied1 and (optionally copied2) are the types of the duplicated words
0345:                Type copied1 = popType();
0346:                Type copied2 = null;
0347:                if (size == 1) {
0348:                    if (copied1.size > 4)
0349:                        throw new Error("using dup for 2-word type");
0350:                } else if (size != 2)
0351:                    throw new Error("invalid size to emitDup");
0352:                else if (copied1.size <= 4) {
0353:                    copied2 = popType();
0354:                    if (copied2.size > 4)
0355:                        throw new Error("dup will cause invalid types on stack");
0356:                }
0357:
0358:                int kind;
0359:                // These are the types of the words (in any) that are "skipped":
0360:                Type skipped1 = null;
0361:                Type skipped2 = null;
0362:                if (offset == 0) {
0363:                    kind = size == 1 ? 89 : 92; // dup or dup2
0364:                } else if (offset == 1) {
0365:                    kind = size == 1 ? 90 : 93; // dup_x1 or dup2_x1
0366:                    skipped1 = popType();
0367:                    if (skipped1.size > 4)
0368:                        throw new Error("dup will cause invalid types on stack");
0369:                } else if (offset == 2) {
0370:                    kind = size == 1 ? 91 : 94; // dup_x2 or dup2_x2
0371:                    skipped1 = popType();
0372:                    if (skipped1.size <= 4) {
0373:                        skipped2 = popType();
0374:                        if (skipped2.size > 4)
0375:                            throw new Error(
0376:                                    "dup will cause invalid types on stack");
0377:                    }
0378:                } else
0379:                    throw new Error("emitDup:  invalid offset");
0380:
0381:                put1(kind);
0382:                if (copied2 != null)
0383:                    pushType(copied2);
0384:                pushType(copied1);
0385:                if (skipped2 != null)
0386:                    pushType(skipped2);
0387:                if (skipped1 != null)
0388:                    pushType(skipped1);
0389:                if (copied2 != null)
0390:                    pushType(copied2);
0391:                pushType(copied1);
0392:            }
0393:
0394:            /**
0395:             * Compile code to duplicate the top 1 or 2 words.
0396:             * @param size number of words to duplicate
0397:             */
0398:            public void emitDup(int size) {
0399:                emitDup(size, 0);
0400:            }
0401:
0402:            /** Duplicate the top element of the given type. */
0403:            public void emitDup(Type type) {
0404:                emitDup(type.size > 4 ? 2 : 1, 0);
0405:            }
0406:
0407:            public void enterScope(Scope scope) {
0408:                scope.setStartPC(PC);
0409:                locals.enterScope(scope);
0410:            }
0411:
0412:            public Scope pushScope() {
0413:                Scope scope = new Scope();
0414:                scope.start_pc = PC;
0415:                readPC = PC;
0416:                if (locals == null)
0417:                    locals = new LocalVarsAttr(getMethod());
0418:                locals.enterScope(scope);
0419:                if (locals.parameter_scope == null)
0420:                    locals.parameter_scope = scope;
0421:                return scope;
0422:            }
0423:
0424:            public Scope getCurrentScope() {
0425:                return locals.current_scope;
0426:            }
0427:
0428:            /** Return the toplevel scope, corresponding to the current method. */
0429:            public Scope methodScope() {
0430:                Scope res = getCurrentScope();
0431:                while (res.parent != null)
0432:                    res = res.parent;
0433:                return res;
0434:            }
0435:
0436:            public Scope popScope() {
0437:                Scope scope = locals.current_scope;
0438:                locals.current_scope = scope.parent;
0439:                scope.end_pc = PC;
0440:                readPC = PC;
0441:                for (Variable var = scope.vars; var != null; var = var.next) {
0442:                    if (var.isSimple() && !var.dead())
0443:                        var.freeLocal(this );
0444:                }
0445:                return scope;
0446:            }
0447:
0448:            /** Get the index'th parameter. */
0449:            public Variable getArg(int index) {
0450:                return locals.parameter_scope.getVariable(index);
0451:            }
0452:
0453:            /**
0454:             * Search by name for a Variable
0455:             * @param name name to search for
0456:             * @return the Variable, or null if not found (in any scope of this Method).
0457:             */
0458:            public Variable lookup(String name) {
0459:                Scope scope = locals.current_scope;
0460:                for (; scope != null; scope = scope.parent) {
0461:                    Variable var = scope.lookup(name);
0462:                    if (var != null)
0463:                        return var;
0464:                }
0465:                return null;
0466:            }
0467:
0468:            /** Add a new local variable (in the current scope).
0469:             * @param type type of the new Variable.
0470:             * @return the new Variable. */
0471:            public Variable addLocal(Type type) {
0472:                return locals.current_scope.addVariable(this , type, null);
0473:            }
0474:
0475:            /** Add a new local variable (in the current scope).
0476:             * @param type type of the new Variable.
0477:             * @param name name of the new Variable.
0478:             * @return the new Variable. */
0479:            public Variable addLocal(Type type, String name) {
0480:                return locals.current_scope.addVariable(this , type, name);
0481:            }
0482:
0483:            /** Call addLocal for parameters (as implied by method type). */
0484:            public void addParamLocals() {
0485:                Method method = getMethod();
0486:                if ((method.access_flags & Access.STATIC) == 0)
0487:                    addLocal(method.classfile).setParameter(true);
0488:                int arg_count = method.arg_types.length;
0489:                for (int i = 0; i < arg_count; i++)
0490:                    addLocal(method.arg_types[i]).setParameter(true);
0491:            }
0492:
0493:            public final void emitPushConstant(int val, Type type) {
0494:                switch (type.getSignature().charAt(0)) {
0495:                case 'B':
0496:                case 'C':
0497:                case 'I':
0498:                case 'Z':
0499:                case 'S':
0500:                    emitPushInt(val);
0501:                    break;
0502:                case 'J':
0503:                    emitPushLong((long) val);
0504:                    break;
0505:                case 'F':
0506:                    emitPushFloat((float) val);
0507:                    break;
0508:                case 'D':
0509:                    emitPushDouble((double) val);
0510:                    break;
0511:                default:
0512:                    throw new Error("bad type to emitPushConstant");
0513:                }
0514:            }
0515:
0516:            public final void emitPushConstant(CpoolEntry cnst) {
0517:                reserve(3);
0518:                int index = cnst.index;
0519:                if (cnst instanceof  CpoolValue2) {
0520:                    put1(20); // ldc2w
0521:                    put2(index);
0522:                } else if (index < 256) {
0523:                    put1(18); // ldc1
0524:                    put1(index);
0525:                } else {
0526:                    put1(19); // ldc2
0527:                    put2(index);
0528:                }
0529:            }
0530:
0531:            public final void emitPushBoolean(boolean b) {
0532:                reserve(1);
0533:                put1(b ? 4 : 3);
0534:                pushType(Type.boolean_type);
0535:            }
0536:
0537:            public final void emitPushInt(int i) {
0538:                reserve(3);
0539:                if (i >= -1 && i <= 5)
0540:                    put1(i + 3); // iconst_m1 .. iconst_5
0541:                else if (i >= -128 && i < 128) {
0542:                    put1(16); // bipush
0543:                    put1(i);
0544:                } else if (i >= -32768 && i < 32768) {
0545:                    put1(17); // sipush
0546:                    put2(i);
0547:                } else {
0548:                    emitPushConstant(getConstants().addInt(i));
0549:                }
0550:                pushType(Type.int_type);
0551:            }
0552:
0553:            public void emitPushLong(long i) {
0554:                if (i == 0 || i == 1) {
0555:                    reserve(1);
0556:                    put1(9 + (int) i); // lconst_0 .. lconst_1
0557:                } else if ((long) (int) i == i) {
0558:                    emitPushInt((int) i);
0559:                    reserve(1);
0560:                    popType();
0561:                    put1(133); // i2l
0562:                } else {
0563:                    emitPushConstant(getConstants().addLong(i));
0564:                }
0565:                pushType(Type.long_type);
0566:            }
0567:
0568:            public void emitPushFloat(float x) {
0569:                int xi = (int) x;
0570:                if ((float) xi == x && xi >= -128 && xi < 128) {
0571:                    if (xi >= 0 && xi <= 2) {
0572:                        reserve(1);
0573:                        put1(11 + xi); // fconst_0 .. fconst_2
0574:                        if (xi == 0 && Float.floatToIntBits(x) != 0) // x == -0.0
0575:                        {
0576:                            reserve(1);
0577:                            put1(118); // fneg
0578:                        }
0579:                    } else {
0580:                        // Saves space in the constant pool
0581:                        // Probably faster, at least on modern CPUs.
0582:                        emitPushInt(xi);
0583:                        reserve(1);
0584:                        popType();
0585:                        put1(134); // i2f
0586:                    }
0587:                } else {
0588:                    emitPushConstant(getConstants().addFloat(x));
0589:                }
0590:                pushType(Type.float_type);
0591:            }
0592:
0593:            public void emitPushDouble(double x) {
0594:                int xi = (int) x;
0595:                if ((double) xi == x && xi >= -128 && xi < 128) {
0596:                    if (xi == 0 || xi == 1) {
0597:                        reserve(1);
0598:                        put1(14 + xi); // dconst_0 or dconst_1
0599:                        if (xi == 0 && Double.doubleToLongBits(x) != 0L) // x == -0.0
0600:                        {
0601:                            reserve(1);
0602:                            put1(119); // dneg
0603:                        }
0604:                    } else {
0605:                        // Saves space in the constant pool
0606:                        // Probably faster, at least on modern CPUs.
0607:                        emitPushInt(xi);
0608:                        reserve(1);
0609:                        popType();
0610:                        put1(135); // i2d
0611:                    }
0612:                } else {
0613:                    emitPushConstant(getConstants().addDouble(x));
0614:                }
0615:                pushType(Type.double_type);
0616:            }
0617:
0618:            public final void emitPushString(String str) {
0619:                emitPushConstant(getConstants().addString(str));
0620:                pushType(Type.string_type);
0621:            }
0622:
0623:            public void emitPushNull() {
0624:                emitPushNull(Type.pointer_type);
0625:            }
0626:
0627:            /**
0628:               @param type the type <code>null</code> is considered to have.
0629:             */
0630:            public void emitPushNull(Type type) {
0631:                reserve(1);
0632:                put1(1); // aconst_null
0633:                pushType(type);
0634:            }
0635:
0636:            public final void emitPushThis() {
0637:                reserve(1);
0638:                put1(42); // aload_0
0639:                pushType(getMethod().getDeclaringClass());
0640:            }
0641:
0642:            void emitNewArray(int type_code) {
0643:                reserve(2);
0644:                put1(188); // newarray
0645:                put1(type_code);
0646:            }
0647:
0648:            public final void emitArrayLength() {
0649:                if (!(popType() instanceof  ArrayType))
0650:                    throw new Error("non-array type in emitArrayLength");
0651:
0652:                reserve(1);
0653:                put1(190); // arraylength
0654:                pushType(Type.int_type);
0655:            }
0656:
0657:            /* Returns an integer in the range 0 (for 'int') through 4 (for object
0658:               reference) to 7 (for 'short') which matches the pattern of how JVM
0659:               opcodes typically depend on the operand type. */
0660:
0661:            private int adjustTypedOp(char sig) {
0662:                switch (sig) {
0663:                case 'I':
0664:                    return 0; // int
0665:                case 'J':
0666:                    return 1; // long
0667:                case 'F':
0668:                    return 2; // float
0669:                case 'D':
0670:                    return 3; // double
0671:                default:
0672:                    return 4; // object
0673:                case 'B':
0674:                case 'Z':
0675:                    return 5; // byte or boolean
0676:                case 'C':
0677:                    return 6; // char
0678:                case 'S':
0679:                    return 7; // short
0680:                }
0681:            }
0682:
0683:            private int adjustTypedOp(Type type) {
0684:                return adjustTypedOp(type.getSignature().charAt(0));
0685:            }
0686:
0687:            private void emitTypedOp(int op, Type type) {
0688:                reserve(1);
0689:                put1(op + adjustTypedOp(type));
0690:            }
0691:
0692:            private void emitTypedOp(int op, char sig) {
0693:                reserve(1);
0694:                put1(op + adjustTypedOp(sig));
0695:            }
0696:
0697:            /** Store into an element of an array.
0698:             * Must already have pushed the array reference, the index,
0699:             * and the new value (in that order).
0700:             * Stack:  ..., array, index, value => ...
0701:             */
0702:            public void emitArrayStore(Type element_type) {
0703:                popType(); // Pop new value
0704:                popType(); // Pop index
0705:                popType(); // Pop array reference
0706:                emitTypedOp(79, element_type);
0707:            }
0708:
0709:            /** Load an element from an array.
0710:             * Must already have pushed the array and the index (in that order):
0711:             * Stack:  ..., array, index => ..., value */
0712:            public void emitArrayLoad(Type element_type) {
0713:                popType(); // Pop index
0714:                popType(); // Pop array reference
0715:                emitTypedOp(46, element_type);
0716:                pushType(element_type);
0717:            }
0718:
0719:            /** Load an element from an array.
0720:             * Must already have pushed the array and the index (in that order):
0721:             * Stack:  ..., array, index => ..., value */
0722:            public void emitArrayLoad() {
0723:                popType(); // Pop index
0724:                ArrayType arrayType = (ArrayType) popType(); // Pop array reference
0725:                Type elementType = arrayType.getComponentType();
0726:                emitTypedOp(46, elementType);
0727:                pushType(elementType);
0728:            }
0729:
0730:            /**
0731:             * Invoke new on a class type.
0732:             * Does not call the constructor!
0733:             * @param type the desired new object type
0734:             */
0735:            public void emitNew(ClassType type) {
0736:                reserve(3);
0737:                put1(187); // new
0738:                putIndex2(getConstants().addClass(type));
0739:                pushType(type);
0740:            }
0741:
0742:            /** Compile code to allocate a new array.
0743:             * The size should have been already pushed on the stack.
0744:             * @param type type of the array elements
0745:             */
0746:            public void emitNewArray(Type element_type, int dims) {
0747:                Type top = popType().promote();
0748:                if (top != Type.int_type)
0749:                    throw new Error("non-int dim. spec. in emitNewArray");
0750:
0751:                if (element_type instanceof  PrimType) {
0752:                    int code;
0753:                    switch (element_type.getSignature().charAt(0)) {
0754:                    case 'B':
0755:                        code = 8;
0756:                        break;
0757:                    case 'S':
0758:                        code = 9;
0759:                        break;
0760:                    case 'I':
0761:                        code = 10;
0762:                        break;
0763:                    case 'J':
0764:                        code = 11;
0765:                        break;
0766:                    case 'F':
0767:                        code = 6;
0768:                        break;
0769:                    case 'D':
0770:                        code = 7;
0771:                        break;
0772:                    case 'Z':
0773:                        code = 4;
0774:                        break;
0775:                    case 'C':
0776:                        code = 5;
0777:                        break;
0778:                    default:
0779:                        throw new Error("bad PrimType in emitNewArray");
0780:                    }
0781:                    emitNewArray(code);
0782:                } else if (element_type instanceof  ArrayType) {
0783:                    reserve(4);
0784:                    put1(197); // multianewarray
0785:                    putIndex2(getConstants().addClass(
0786:                            new ArrayType(element_type)));
0787:                    if (dims < 1 || dims > 255)
0788:                        throw new Error("dims out of range in emitNewArray");
0789:                    put1(dims);
0790:                    while (--dims > 0) // first dim already popped
0791:                    {
0792:                        top = popType().promote();
0793:                        if (top != Type.int_type)
0794:                            throw new Error(
0795:                                    "non-int dim. spec. in emitNewArray");
0796:                    }
0797:                } else if (element_type instanceof  ObjectType) {
0798:                    reserve(3);
0799:                    put1(189); // anewarray
0800:                    putIndex2(getConstants()
0801:                            .addClass((ObjectType) element_type));
0802:                } else
0803:                    throw new Error("unimplemented type in emitNewArray");
0804:
0805:                pushType(new ArrayType(element_type));
0806:            }
0807:
0808:            public void emitNewArray(Type element_type) {
0809:                emitNewArray(element_type, 1);
0810:            }
0811:
0812:            // We may want to deprecate this, because it depends on popType.
0813:            private void emitBinop(int base_code) {
0814:                Type type2 = popType().promote();
0815:                Type type1_raw = popType();
0816:                Type type1 = type1_raw.promote();
0817:                if (type1 != type2 || !(type1 instanceof  PrimType))
0818:                    throw new Error(
0819:                            "non-matching or bad types in binary operation");
0820:                emitTypedOp(base_code, type1);
0821:                pushType(type1_raw);
0822:            }
0823:
0824:            private void emitBinop(int base_code, char sig) {
0825:                popType();
0826:                popType();
0827:                emitTypedOp(base_code, sig);
0828:                pushType(Type.signatureToPrimitive(sig));
0829:            }
0830:
0831:            private void emitBinop(int base_code, Type type) {
0832:                popType();
0833:                popType();
0834:                emitTypedOp(base_code, type);
0835:                pushType(type);
0836:            }
0837:
0838:            // public final void emitIntAdd () { put1(96); popType();}
0839:            // public final void emitLongAdd () { put1(97); popType();}
0840:            // public final void emitFloatAdd () { put1(98); popType();}
0841:            // public final void emitDoubleAdd () { put1(99); popType();}
0842:
0843:            public final void emitAdd(char sig) {
0844:                emitBinop(96, sig);
0845:            }
0846:
0847:            public final void emitAdd(PrimType type) {
0848:                emitBinop(96, type);
0849:            }
0850:
0851:            /** @deprecated */
0852:            public final void emitAdd() {
0853:                emitBinop(96);
0854:            }
0855:
0856:            public final void emitSub(char sig) {
0857:                emitBinop(100, sig);
0858:            }
0859:
0860:            public final void emitSub(PrimType type) {
0861:                emitBinop(100, type);
0862:            }
0863:
0864:            /** @deprecated */
0865:            public final void emitSub() {
0866:                emitBinop(100);
0867:            }
0868:
0869:            public final void emitMul() {
0870:                emitBinop(104);
0871:            }
0872:
0873:            public final void emitDiv() {
0874:                emitBinop(108);
0875:            }
0876:
0877:            public final void emitRem() {
0878:                emitBinop(112);
0879:            }
0880:
0881:            public final void emitAnd() {
0882:                emitBinop(126);
0883:            }
0884:
0885:            public final void emitIOr() {
0886:                emitBinop(128);
0887:            }
0888:
0889:            public final void emitXOr() {
0890:                emitBinop(130);
0891:            }
0892:
0893:            public final void emitShl() {
0894:                emitShift(120);
0895:            }
0896:
0897:            public final void emitShr() {
0898:                emitShift(122);
0899:            }
0900:
0901:            public final void emitUshr() {
0902:                emitShift(124);
0903:            }
0904:
0905:            private void emitShift(int base_code) {
0906:                Type type2 = popType().promote();
0907:                Type type1_raw = popType();
0908:                Type type1 = type1_raw.promote();
0909:
0910:                if (type2 != Type.int_type)
0911:                    throw new Error("the amount of shift must be an int");
0912:                if (type1 != Type.int_type && type1 != Type.long_type)
0913:                    throw new Error(
0914:                            "the value shifted must be an int or a long");
0915:                emitTypedOp(base_code, type1);
0916:                pushType(type1_raw);
0917:            }
0918:
0919:            /** Unary numerical negation (-). */
0920:            public final void emitNeg() {
0921:                Type type = popType().promote();
0922:                emitTypedOp(116, type);
0923:                pushType(type);
0924:            }
0925:
0926:            public final void emitNot(Type type) {
0927:                emitPushConstant(1, type);
0928:                emitAdd();
0929:                emitPushConstant(1, type);
0930:                emitAnd();
0931:            }
0932:
0933:            public void emitPrimop(int opcode, int arg_count, Type retType) {
0934:                reserve(1);
0935:                while (--arg_count >= 0)
0936:                    popType();
0937:                put1(opcode);
0938:                pushType(retType);
0939:            }
0940:
0941:            void emitMaybeWide(int opcode, int index) {
0942:                if (index >= 256) {
0943:                    put1(196); // wide
0944:                    put1(opcode);
0945:                    put2(index);
0946:                } else {
0947:                    put1(opcode);
0948:                    put1(index);
0949:                }
0950:            }
0951:
0952:            /**
0953:             * Comple code to push the contents of a local variable onto the statck.
0954:             * @param var The variable whose contents we want to push.
0955:             */
0956:            public final void emitLoad(Variable var) {
0957:                if (var.dead())
0958:                    throw new Error("attempting to push dead variable");
0959:                int offset = var.offset;
0960:                if (offset < 0 || !var.isSimple())
0961:                    throw new Error(
0962:                            "attempting to load from unassigned variable "
0963:                                    + var + " simple:" + var.isSimple()
0964:                                    + ", offset: " + offset);
0965:                Type type = var.getType().promote();
0966:                reserve(4);
0967:                int kind = adjustTypedOp(type);
0968:                if (offset <= 3)
0969:                    put1(26 + 4 * kind + offset); // [ilfda]load_[0123]
0970:                else
0971:                    emitMaybeWide(21 + kind, offset); // [ilfda]load
0972:                pushType(var.getType());
0973:            }
0974:
0975:            public void emitStore(Variable var) {
0976:                if (var.dead())
0977:                    throw new Error("attempting to push dead variable" + var);
0978:                int offset = var.offset;
0979:                if (offset < 0 || !var.isSimple())
0980:                    throw new Error(
0981:                            "attempting to store in unassigned variable "
0982:                                    + var.getName() + " simple:"
0983:                                    + var.isSimple() + ", offset: " + offset);
0984:                Type type = var.getType().promote();
0985:                reserve(4);
0986:                popType();
0987:                int kind = adjustTypedOp(type);
0988:                if (offset <= 3)
0989:                    put1(59 + 4 * kind + offset); // [ilfda]store_[0123]
0990:                else
0991:                    emitMaybeWide(54 + kind, offset); // [ilfda]store
0992:            }
0993:
0994:            public void emitInc(Variable var, short inc) {
0995:                if (var.dead())
0996:                    throw new Error("attempting to increment dead variable");
0997:                int offset = var.offset;
0998:                if (offset < 0 || !var.isSimple())
0999:                    throw new Error(
1000:                            "attempting to increment unassigned variable"
1001:                                    + var.getName() + " simple:"
1002:                                    + var.isSimple() + ", offset: " + offset);
1003:                Type type = var.getType().promote();
1004:                reserve(6);
1005:                if (type != Type.int_type)
1006:                    throw new Error("attempting to increment non-int variable");
1007:
1008:                boolean wide = offset > 255 || inc > 255 || inc < -256;
1009:
1010:                if (wide) {
1011:                    put1(196); // wide
1012:                    put1(132); // iinc
1013:                    put2(offset);
1014:                    put2(inc);
1015:                } else {
1016:                    put1(132); // iinc
1017:                    put1(offset);
1018:                    put1(inc);
1019:                }
1020:            }
1021:
1022:            private final void emitFieldop(Field field, int opcode) {
1023:                reserve(3);
1024:                put1(opcode);
1025:                putIndex2(getConstants().addFieldRef(field));
1026:            }
1027:
1028:            /** Compile code to get a static field value.
1029:             * Stack:  ... => ..., value */
1030:
1031:            public final void emitGetStatic(Field field) {
1032:                pushType(field.type);
1033:                emitFieldop(field, 178); // getstatic
1034:            }
1035:
1036:            /** Compile code to get a non-static field value.
1037:             * Stack:  ..., objectref => ..., value */
1038:
1039:            public final void emitGetField(Field field) {
1040:                popType();
1041:                pushType(field.type);
1042:                emitFieldop(field, 180); // getfield
1043:            }
1044:
1045:            /** Compile code to put a static field value.
1046:             * Stack:  ..., value => ... */
1047:
1048:            public final void emitPutStatic(Field field) {
1049:                popType();
1050:                emitFieldop(field, 179); // putstatic
1051:            }
1052:
1053:            /** Compile code to put a non-static field value.
1054:             * Stack:  ..., objectref, value => ... */
1055:
1056:            public final void emitPutField(Field field) {
1057:                popType();
1058:                popType();
1059:                emitFieldop(field, 181); // putfield
1060:            }
1061:
1062:            /** Comptes the number of stack words taken by a list of types. */
1063:            private int words(Type[] types) {
1064:                int res = 0;
1065:                for (int i = types.length; --i >= 0;)
1066:                    if (types[i].size > 4)
1067:                        res += 2;
1068:                    else
1069:                        res++;
1070:                return res;
1071:            }
1072:
1073:            public void emitInvokeMethod(Method method, int opcode) {
1074:                reserve(opcode == 185 ? 5 : 3);
1075:                int arg_count = method.arg_types.length;
1076:                boolean is_invokestatic = opcode == 184;
1077:                if (is_invokestatic != ((method.access_flags & Access.STATIC) != 0))
1078:                    throw new Error(
1079:                            "emitInvokeXxx static flag mis-match method.flags="
1080:                                    + method.access_flags);
1081:                Type receiverType = null;
1082:
1083:                while (--arg_count >= 0)
1084:                    popType();
1085:                if (!is_invokestatic) {
1086:                    arg_count++;
1087:                    receiverType = popType();
1088:                    // Don't change anything if the call is an invokespecial
1089:                    if (opcode != 183
1090:                            && receiverType != method.getDeclaringClass()) {
1091:                        // We try to find a more precise method, given the known
1092:                        // type of the receiver.
1093:                        Method preciseMethod = receiverType
1094:                                .refineMethod(method);
1095:
1096:                        if (preciseMethod != null &&
1097:                        // Don't choose a more precise method if it is an
1098:                                // interface method, and the original is a class method
1099:                                // (can happen if the original class is Object, like in
1100:                                // Object.equals, refined in List.equals).
1101:                                ((!preciseMethod.getDeclaringClass()
1102:                                        .isInterface()) || method
1103:                                        .getDeclaringClass().isInterface())) {
1104:                            method = preciseMethod;
1105:                            // It could be that the call was an invokeinterface, and
1106:                            // now became an invokevirtual.
1107:                            if (opcode == 185
1108:                                    && !method.getDeclaringClass()
1109:                                            .isInterface())
1110:                                opcode = 182;
1111:                        }
1112:                    }
1113:                }
1114:
1115:                if (!Access.legal(getMethod().getDeclaringClass(), method,
1116:                        receiverType))
1117:                    throw new VerificationError("Method " + method.toString()
1118:                            + " is not accessible");
1119:
1120:                put1(opcode); // invokevirtual, invokespecial, or invokestatic
1121:                putIndex2(getConstants().addMethodRef(method));
1122:                if (opcode == 185) // invokeinterface
1123:                {
1124:                    put1(words(method.arg_types) + 1); // 1 word for 'this'
1125:                    put1(0);
1126:                }
1127:                if (method.return_type.size != 0)
1128:                    pushType(method.return_type);
1129:            }
1130:
1131:            public void emitInvoke(Method method) {
1132:                int opcode;
1133:                if ((method.access_flags & Access.STATIC) != 0)
1134:                    opcode = 184; // invokestatic
1135:                else if (method.classfile.isInterface())
1136:                    opcode = 185; // invokeinterface
1137:                else
1138:                    opcode = 182; // invokevirtual
1139:                emitInvokeMethod(method, opcode);
1140:            }
1141:
1142:            /** Compile a virtual method call.
1143:             * The stack contains the 'this' object, followed by the arguments in order.
1144:             * @param method the method to invoke virtually
1145:             */
1146:            public void emitInvokeVirtual(Method method) {
1147:                emitInvokeMethod(method, 182); // invokevirtual
1148:            }
1149:
1150:            public void emitInvokeSpecial(Method method) {
1151:                emitInvokeMethod(method, 183); // invokespecial
1152:            }
1153:
1154:            /** Compile a static method call.
1155:             * The stack contains the the arguments in order.
1156:             * @param method the static method to invoke
1157:             */
1158:            public void emitInvokeStatic(Method method) {
1159:                emitInvokeMethod(method, 184); // invokestatic
1160:            }
1161:
1162:            public void emitInvokeInterface(Method method) {
1163:                emitInvokeMethod(method, 185); // invokeinterface
1164:            }
1165:
1166:            final void emitTransfer(Label label, int opcode) {
1167:                put1(opcode);
1168:                label.emit(this );
1169:            }
1170:
1171:            /** Compile an unconditional branch (goto) or a jsr.
1172:             * @param label target of the branch (must be in this method).
1173:             */
1174:            public final void emitGoto(Label label, int opcode) {
1175:                reserve(5);
1176:                if (label.defined()) {
1177:                    readPC = PC;
1178:                    int delta = label.position - PC;
1179:                    if (delta < -32768) {
1180:                        put1(opcode - 167); // goto_w or jsr_w
1181:                        put4(delta);
1182:                    } else {
1183:                        put1(opcode); // goto or jsr
1184:                        put2(delta);
1185:                    }
1186:                } else
1187:                    emitTransfer(label, opcode); // goto label or jsr label
1188:            }
1189:
1190:            /** Compile an unconditional branch (goto).
1191:             * @param label target of the branch (must be in this method).
1192:             */
1193:            public final void emitGoto(Label label) {
1194:                emitGoto(label, 167);
1195:                setUnreachable();
1196:            }
1197:
1198:            public final void emitJsr(Label label) {
1199:                emitGoto(label, 168);
1200:            }
1201:
1202:            public final void emitGotoIfEq(Label label, boolean invert) {
1203:                Type type2 = popType().promote();
1204:                Type type1 = popType().promote();
1205:                reserve(4);
1206:                int opcode;
1207:                char sig1 = type1.getSignature().charAt(0);
1208:                char sig2 = type2.getSignature().charAt(0);
1209:                if (sig1 == 'I' && sig2 == 'I')
1210:                    opcode = 159; // if_icmpeq (inverted: if_icmpne)
1211:                else if (sig1 == 'J' && sig2 == 'J') {
1212:                    put1(148); // lcmp
1213:                    opcode = 153; // ifeq (inverted: ifne)
1214:                } else if (sig1 == 'F' && sig2 == 'F') {
1215:                    put1(149); // fcmpl
1216:                    opcode = 153; // ifeq (inverted: ifne)
1217:                } else if (sig1 == 'D' && sig2 == 'D') {
1218:                    put1(151); // dcmpl
1219:                    opcode = 153; // ifeq (inverted: ifne)
1220:                } else if ((sig1 == 'L' || sig1 == '[')
1221:                        && (sig2 == 'L' || sig2 == '['))
1222:                    opcode = 165; // if_acmpeq (inverted: if_acmpne)
1223:                else
1224:                    throw new Error("non-matching types to emitGotoIfEq");
1225:                if (invert)
1226:                    opcode++;
1227:                emitTransfer(label, opcode);
1228:            }
1229:
1230:            /** Compile a conditional transfer if 2 top stack elements are equal. */
1231:            public final void emitGotoIfEq(Label label) {
1232:                emitGotoIfEq(label, false);
1233:            }
1234:
1235:            /** Compile conditional transfer if 2 top stack elements are not equal. */
1236:            public final void emitGotoIfNE(Label label) {
1237:                emitGotoIfEq(label, true);
1238:            }
1239:
1240:            public final void emitGotoIfCompare1(Label label, int opcode) {
1241:                popType();
1242:                reserve(3);
1243:                emitTransfer(label, opcode);
1244:            }
1245:
1246:            public final void emitGotoIfIntEqZero(Label label) {
1247:                emitGotoIfCompare1(label, 153);
1248:            }
1249:
1250:            public final void emitGotoIfIntNeZero(Label label) {
1251:                emitGotoIfCompare1(label, 154);
1252:            }
1253:
1254:            public final void emitGotoIfIntLtZero(Label label) {
1255:                emitGotoIfCompare1(label, 155);
1256:            }
1257:
1258:            public final void emitGotoIfIntGeZero(Label label) {
1259:                emitGotoIfCompare1(label, 156);
1260:            }
1261:
1262:            public final void emitGotoIfIntGtZero(Label label) {
1263:                emitGotoIfCompare1(label, 157);
1264:            }
1265:
1266:            public final void emitGotoIfIntLeZero(Label label) {
1267:                emitGotoIfCompare1(label, 158);
1268:            }
1269:
1270:            public final void emitGotoIfNull(Label label) {
1271:                emitGotoIfCompare1(label, 198);
1272:            } //ifnull
1273:
1274:            public final void emitGotoIfNotNull(Label label) {
1275:                emitGotoIfCompare1(label, 199);
1276:            } //ifnonnull
1277:
1278:            public final void emitGotoIfCompare2(Label label, int logop) {
1279:                if (logop < 155 || logop > 158)
1280:                    throw new Error(
1281:                            "emitGotoIfCompare2: logop must be one of iflt, ifgt, ifle, ifge");
1282:
1283:                Type type2 = popType().promote();
1284:                Type type1 = popType().promote();
1285:                reserve(4);
1286:                char sig1 = type1.getSignature().charAt(0);
1287:                char sig2 = type2.getSignature().charAt(0);
1288:
1289:                boolean cmpg = (logop == 155 || logop == 158); // iflt,ifle
1290:
1291:                if (sig1 == 'I' && sig2 == 'I')
1292:                    logop += 6; // iflt -> if_icmplt etc.
1293:                else if (sig1 == 'J' && sig2 == 'J')
1294:                    put1(148); // lcmp
1295:                else if (sig1 == 'F' && sig2 == 'F')
1296:                    put1(cmpg ? 149 : 150); // fcmpl/fcmpg
1297:                else if (sig1 == 'D' && sig2 == 'D')
1298:                    put1(cmpg ? 151 : 152); // dcmpl/dcmpg
1299:                else
1300:                    throw new Error("non-matching types to emitGotoIfCompare2");
1301:
1302:                emitTransfer(label, logop);
1303:            }
1304:
1305:            // binary comparisons
1306:            public final void emitGotoIfLt(Label label) {
1307:                emitGotoIfCompare2(label, 155);
1308:            }
1309:
1310:            public final void emitGotoIfGe(Label label) {
1311:                emitGotoIfCompare2(label, 156);
1312:            }
1313:
1314:            public final void emitGotoIfGt(Label label) {
1315:                emitGotoIfCompare2(label, 157);
1316:            }
1317:
1318:            public final void emitGotoIfLe(Label label) {
1319:                emitGotoIfCompare2(label, 158);
1320:            }
1321:
1322:            /** Compile start of a conditional:  if (!(x OPCODE 0)) ...
1323:             * The value of x must already have been pushed. */
1324:            public final void emitIfCompare1(int opcode) {
1325:                IfState new_if = new IfState(this );
1326:                if (popType().promote() != Type.int_type)
1327:                    throw new Error("non-int type to emitIfCompare1");
1328:                reserve(3);
1329:                emitTransfer(new_if.end_label, opcode);
1330:                new_if.start_stack_size = SP;
1331:            }
1332:
1333:            /** Compile start of conditional:  if (x != 0) ...
1334:             * Also use this if you have pushed a boolean value:  if (b) ... */
1335:            public final void emitIfIntNotZero() {
1336:                emitIfCompare1(153); // ifeq
1337:            }
1338:
1339:            /** Compile start of conditional:  if (x == 0) ...
1340:             * Also use this if you have pushed a boolean value:  if (!b) ... */
1341:            public final void emitIfIntZero() {
1342:                emitIfCompare1(154); // ifne
1343:            }
1344:
1345:            /** Compile start of conditional:  if (x <= 0) */
1346:            public final void emitIfIntLEqZero() {
1347:                emitIfCompare1(157); // ifgt
1348:            }
1349:
1350:            /** Compile start of a conditional:  if (!(x OPCODE null)) ...
1351:             * The value of x must already have been pushed and must be of
1352:             * reference type. */
1353:            public final void emitIfRefCompare1(int opcode) {
1354:                IfState new_if = new IfState(this );
1355:                if (!(popType() instanceof  ObjectType))
1356:                    throw new Error("non-ref type to emitIfRefCompare1");
1357:                reserve(3);
1358:                emitTransfer(new_if.end_label, opcode);
1359:                new_if.start_stack_size = SP;
1360:            }
1361:
1362:            /** Compile start of conditional:  if (x != null) */
1363:            public final void emitIfNotNull() {
1364:                emitIfRefCompare1(198); // ifnull
1365:            }
1366:
1367:            /** Compile start of conditional:  if (x == null) */
1368:            public final void emitIfNull() {
1369:                emitIfRefCompare1(199); // ifnonnull
1370:            }
1371:
1372:            /** Compile start of a conditional:  if (!(x OPCODE y)) ...
1373:             * The value of x and y must already have been pushed. */
1374:            public final void emitIfIntCompare(int opcode) {
1375:                IfState new_if = new IfState(this );
1376:                popType();
1377:                popType();
1378:                reserve(3);
1379:                emitTransfer(new_if.end_label, opcode);
1380:                new_if.start_stack_size = SP;
1381:            }
1382:
1383:            /* Compile start of a conditional:  if (x < y) ... */
1384:            public final void emitIfIntLt() {
1385:                emitIfIntCompare(162); // if_icmpge
1386:            }
1387:
1388:            /** Compile start of a conditional:  if (x != y) ...
1389:             * The values of x and y must already have been pushed. */
1390:            public final void emitIfNEq() {
1391:                IfState new_if = new IfState(this );
1392:                emitGotoIfEq(new_if.end_label);
1393:                new_if.start_stack_size = SP;
1394:            }
1395:
1396:            /** Compile start of a conditional:  if (x == y) ...
1397:             * The values of x and y must already have been pushed. */
1398:            public final void emitIfEq() {
1399:                IfState new_if = new IfState(this );
1400:                emitGotoIfNE(new_if.end_label);
1401:                new_if.start_stack_size = SP;
1402:            }
1403:
1404:            /** Compile start of a conditional:  if (x < y) ...
1405:             * The values of x and y must already have been pushed. */
1406:            public final void emitIfLt() {
1407:                IfState new_if = new IfState(this );
1408:                emitGotoIfGe(new_if.end_label);
1409:                new_if.start_stack_size = SP;
1410:            }
1411:
1412:            /** Compile start of a conditional:  if (x >= y) ...
1413:             * The values of x and y must already have been pushed. */
1414:            public final void emitIfGe() {
1415:                IfState new_if = new IfState(this );
1416:                emitGotoIfLt(new_if.end_label);
1417:                new_if.start_stack_size = SP;
1418:            }
1419:
1420:            /** Compile start of a conditional:  if (x > y) ...
1421:             * The values of x and y must already have been pushed. */
1422:            public final void emitIfGt() {
1423:                IfState new_if = new IfState(this );
1424:                emitGotoIfLe(new_if.end_label);
1425:                new_if.start_stack_size = SP;
1426:            }
1427:
1428:            /** Compile start of a conditional:  if (x <= y) ...
1429:             * The values of x and y must already have been pushed. */
1430:            public final void emitIfLe() {
1431:                IfState new_if = new IfState(this );
1432:                emitGotoIfGt(new_if.end_label);
1433:                new_if.start_stack_size = SP;
1434:            }
1435:
1436:            /** Emit a 'ret' instruction.
1437:             * @param var the variable containing the return address */
1438:            public void emitRet(Variable var) {
1439:                int offset = var.offset;
1440:                if (offset < 256) {
1441:                    reserve(2);
1442:                    put1(169); // ret
1443:                    put1(offset);
1444:                } else {
1445:                    reserve(4);
1446:                    put1(196); // wide
1447:                    put1(169); // ret
1448:                    put2(offset);
1449:                }
1450:            }
1451:
1452:            public final void emitIfThen() {
1453:                new IfState(this , null);
1454:            }
1455:
1456:            /** Compile start of else clause. */
1457:            public final void emitElse() {
1458:                Label else_label = if_stack.end_label;
1459:                Label end_label = new Label(this );
1460:                if_stack.end_label = end_label;
1461:                if (reachableHere()) {
1462:                    int growth = SP - if_stack.start_stack_size;
1463:                    if_stack.stack_growth = growth;
1464:                    if (growth > 0) {
1465:                        if_stack.then_stacked_types = new Type[growth];
1466:                        System.arraycopy(stack_types,
1467:                                if_stack.start_stack_size,
1468:                                if_stack.then_stacked_types, 0, growth);
1469:                    } else
1470:                        if_stack.then_stacked_types = new Type[0]; // ???
1471:                    emitGoto(end_label);
1472:                }
1473:                while (SP > if_stack.start_stack_size)
1474:                    popType();
1475:                SP = if_stack.start_stack_size;
1476:                if (else_label != null)
1477:                    else_label.define(this );
1478:                if_stack.doing_else = true;
1479:            }
1480:
1481:            /** Compile end of conditional. */
1482:            public final void emitFi() {
1483:                boolean make_unreachable = false;
1484:                if (!if_stack.doing_else) { // There was no 'else' clause.
1485:                    if (reachableHere() && SP != if_stack.start_stack_size)
1486:                        throw new Error(
1487:                                "at PC "
1488:                                        + PC
1489:                                        + " then clause grows stack with no else clause");
1490:                } else if (if_stack.then_stacked_types != null) {
1491:                    int then_clause_stack_size = if_stack.start_stack_size
1492:                            + if_stack.stack_growth;
1493:                    if (!reachableHere()) {
1494:                        if (if_stack.stack_growth > 0)
1495:                            System.arraycopy(if_stack.then_stacked_types, 0,
1496:                                    stack_types, if_stack.start_stack_size,
1497:                                    if_stack.stack_growth);
1498:                        SP = then_clause_stack_size;
1499:                    } else if (SP != then_clause_stack_size) {
1500:                        for (int i = 0; i < if_stack.then_stacked_types.length; i++)
1501:                            System.out.println("Stack[" + i + "] = "
1502:                                    + if_stack.then_stacked_types[i]);
1503:                        throw new Error("at PC " + PC
1504:                                + ": SP at end of 'then' was "
1505:                                + then_clause_stack_size
1506:                                + " while SP at end of 'else' was " + SP);
1507:                    } else {
1508:                        // Reconcile the types on the stack.
1509:                        for (int i = 0; i < if_stack.then_stacked_types.length; i++) {
1510:                            Type t1 = if_stack.then_stacked_types[i];
1511:                            Type t2 = stack_types[if_stack.start_stack_size + i];
1512:
1513:                            Type common = Type.lowestCommonSuperType(t1, t2);
1514:                            if (common == null)
1515:                                common = Type.pointer_type;
1516:
1517:                            stack_types[if_stack.start_stack_size + i] = common;
1518:                        }
1519:                    }
1520:                } else if (unreachable_here)
1521:                    make_unreachable = true;
1522:
1523:                if (if_stack.end_label != null)
1524:                    if_stack.end_label.define(this );
1525:                if (make_unreachable)
1526:                    setUnreachable();
1527:                // Pop the if_stack.
1528:                if_stack = if_stack.previous;
1529:            }
1530:
1531:            public final void emitConvert(Type from, Type to) {
1532:                String to_sig = to.getSignature();
1533:                String from_sig = from.getSignature();
1534:                int op = -1;
1535:                if (to_sig.length() == 1 || from_sig.length() == 1) {
1536:                    char to_sig0 = to_sig.charAt(0);
1537:                    char from_sig0 = from_sig.charAt(0);
1538:                    if (from_sig0 == to_sig0)
1539:                        return;
1540:                    if (from.size < 4)
1541:                        from_sig0 = 'I';
1542:                    if (to.size < 4) {
1543:                        emitConvert(from, Type.int_type);
1544:                        from_sig0 = 'I';
1545:                    }
1546:                    if (from_sig0 == to_sig0)
1547:                        return;
1548:                    switch (from_sig0) {
1549:                    case 'I':
1550:                        switch (to_sig0) {
1551:                        case 'B':
1552:                            op = 145;
1553:                            break; // i2b
1554:                        case 'C':
1555:                            op = 146;
1556:                            break; // i2c
1557:                        case 'S':
1558:                            op = 147;
1559:                            break; // i2s
1560:                        case 'J':
1561:                            op = 133;
1562:                            break; // i2l
1563:                        case 'F':
1564:                            op = 134;
1565:                            break; // i2f
1566:                        case 'D':
1567:                            op = 135;
1568:                            break; // i2d
1569:                        }
1570:                        break;
1571:                    case 'J':
1572:                        switch (to_sig0) {
1573:                        case 'I':
1574:                            op = 136;
1575:                            break; // l2i
1576:                        case 'F':
1577:                            op = 137;
1578:                            break; // l2f
1579:                        case 'D':
1580:                            op = 138;
1581:                            break; // l2d
1582:                        }
1583:                        break;
1584:                    case 'F':
1585:                        switch (to_sig0) {
1586:                        case 'I':
1587:                            op = 139;
1588:                            break; // f2i
1589:                        case 'J':
1590:                            op = 140;
1591:                            break; // f2l
1592:                        case 'D':
1593:                            op = 141;
1594:                            break; // f2d
1595:                        }
1596:                        break;
1597:                    case 'D':
1598:                        switch (to_sig0) {
1599:                        case 'I':
1600:                            op = 142;
1601:                            break; // d2i
1602:                        case 'J':
1603:                            op = 143;
1604:                            break; // d2l
1605:                        case 'F':
1606:                            op = 144;
1607:                            break; // d2f
1608:                        }
1609:                        break;
1610:                    }
1611:                }
1612:                if (op < 0)
1613:                    throw new Error("unsupported CodeAttr.emitConvert from "
1614:                            + from + " to " + to);
1615:                reserve(1);
1616:                popType();
1617:                put1(op);
1618:                pushType(to);
1619:            }
1620:
1621:            private void emitCheckcast(Type type, int opcode) {
1622:                reserve(3);
1623:                popType();
1624:                put1(opcode);
1625:                //      if (type instanceof ArrayType)
1626:                //        {
1627:                //  	ArrayType atype = (ArrayType) type;
1628:                //  	CpoolUtf8 name = getConstants().addUtf8(atype.signature);
1629:                //  	putIndex2(getConstants().addClass(name));
1630:                //        } else
1631:                if (type instanceof  ObjectType) {
1632:                    putIndex2(getConstants().addClass((ObjectType) type));
1633:                } else
1634:                    throw new Error("unimplemented type " + type
1635:                            + " in emitCheckcast/emitInstanceof");
1636:            }
1637:
1638:            public void emitCheckcast(Type type) {
1639:                emitCheckcast(type, 192);
1640:                pushType(type);
1641:            }
1642:
1643:            public void emitInstanceof(Type type) {
1644:                emitCheckcast(type, 193);
1645:                pushType(Type.boolean_type);
1646:            }
1647:
1648:            public final void emitThrow() {
1649:                popType();
1650:                reserve(1);
1651:                put1(191); // athrow
1652:                setUnreachable();
1653:            }
1654:
1655:            public final void emitMonitorEnter() {
1656:                popType();
1657:                reserve(1);
1658:                put1(194); // monitorenter
1659:            }
1660:
1661:            public final void emitMonitorExit() {
1662:                popType();
1663:                reserve(1);
1664:                put1(195); // monitorexit
1665:            }
1666:
1667:            private void callFinallyBlocks() {
1668:                TryState state = try_stack;
1669:
1670:                /* If a value is returned, it must be saved to a local variable,
1671:                   to prevent a verification error because of inconsistent stack sizes.
1672:                 */
1673:                boolean saveResult = !getMethod().getReturnType().isVoid();
1674:                Variable result = null;
1675:
1676:                while (state != null) {
1677:                    if (state.finally_subr != null // there is a finally block
1678:                            && state.finally_ret_addr == null) // 'return' is not inside it
1679:                    {
1680:                        if (saveResult && result == null) {
1681:                            // We store the result in a method-level variable, to make sure
1682:                            // that the finally blocks do not use the same slot.
1683:                            result = methodScope().addVariable(this , topType(),
1684:                                    null);
1685:                            emitStore(result);
1686:                        }
1687:                        emitJsr(state.finally_subr);
1688:                    }
1689:
1690:                    state = state.previous;
1691:                }
1692:
1693:                if (result != null)
1694:                    emitLoad(result);
1695:            }
1696:
1697:            /**
1698:             * Compile a method return.
1699:             */
1700:            public final void emitReturn() {
1701:                callFinallyBlocks();
1702:                if (!checkPostcondition())
1703:                    emitRealReturn();
1704:            }
1705:
1706:            private void emitRealReturn() {
1707:                if (getMethod().getReturnType().size == 0) {
1708:                    reserve(1);
1709:                    put1(177); // return
1710:                } else
1711:                    emitTypedOp(172, popType().promote());
1712:                setUnreachable();
1713:            }
1714:
1715:            /** Add an exception handler. */
1716:            public void addHandler(int start_pc, int end_pc, int handler_pc,
1717:                    int catch_type) {
1718:                int index = 4 * exception_table_length;
1719:                if (exception_table == null) {
1720:                    exception_table = new short[20];
1721:                } else if (exception_table.length <= index) {
1722:                    short[] new_table = new short[2 * exception_table.length];
1723:                    System.arraycopy(exception_table, 0, new_table, 0, index);
1724:                    exception_table = new_table;
1725:                }
1726:                exception_table[index++] = (short) start_pc;
1727:                exception_table[index++] = (short) end_pc;
1728:                exception_table[index++] = (short) handler_pc;
1729:                exception_table[index++] = (short) catch_type;
1730:                exception_table_length++;
1731:            }
1732:
1733:            /** Add an exception handler. */
1734:            public void addHandler(int start_pc, int end_pc, int handler_pc,
1735:                    ClassType catch_type, ConstantPool constants) {
1736:                int catch_type_index;
1737:                if (catch_type == null)
1738:                    catch_type_index = 0;
1739:                else
1740:                    catch_type_index = constants.addClass(catch_type).index;
1741:                addHandler(start_pc, end_pc, handler_pc, catch_type_index);
1742:            }
1743:
1744:            public void emitTryStart(boolean has_finally, Type result_type) {
1745:                Variable[] savedStack;
1746:                if (SP > 0) {
1747:                    savedStack = new Variable[SP];
1748:                    int i = 0;
1749:                    while (SP > 0) {
1750:                        Variable var = addLocal(topType());
1751:                        emitStore(var);
1752:                        savedStack[i++] = var;
1753:                    }
1754:                } else
1755:                    savedStack = null;
1756:                TryState try_state = new TryState(this );
1757:                try_state.savedStack = savedStack;
1758:                if (result_type != null && result_type.size == 0) // void
1759:                    result_type = null;
1760:                if (result_type != null || SP > 0) {
1761:                    pushScope();
1762:                    if (result_type != null)
1763:                        try_state.saved_result = addLocal(result_type);
1764:                }
1765:                if (has_finally)
1766:                    try_state.finally_subr = new Label(this );
1767:            }
1768:
1769:            public void emitTryEnd() {
1770:                if (try_stack.end_label == null) {
1771:                    if (try_stack.saved_result != null)
1772:                        emitStore(try_stack.saved_result);
1773:                    try_stack.end_label = new Label(this );
1774:                    if (reachableHere()) {
1775:                        if (try_stack.finally_subr != null)
1776:                            emitGoto(try_stack.finally_subr, 168); // jsr
1777:                        emitGoto(try_stack.end_label);
1778:                    }
1779:                    readPC = PC;
1780:                    try_stack.end_pc = PC;
1781:                }
1782:            }
1783:
1784:            public void emitCatchStart(Variable var) {
1785:                emitTryEnd();
1786:                SP = 0;
1787:                if (try_stack.try_type != null)
1788:                    emitCatchEnd();
1789:                ClassType type = var == null ? null : (ClassType) var.getType();
1790:                try_stack.try_type = type;
1791:                readPC = PC;
1792:                addHandler(try_stack.start_pc, try_stack.end_pc, PC, type,
1793:                        getConstants());
1794:                if (var != null) {
1795:                    pushType(type);
1796:                    emitStore(var);
1797:                } else
1798:                    pushType(Type.throwable_type);
1799:            }
1800:
1801:            public void emitCatchStart(ClassType type) {
1802:                emitTryEnd();
1803:                SP = 0;
1804:                if (try_stack.try_type != null)
1805:                    emitCatchEnd();
1806:                try_stack.try_type = type;
1807:                readPC = PC;
1808:                addHandler(try_stack.start_pc, try_stack.end_pc, PC, type,
1809:                        getConstants());
1810:                pushType(type);
1811:            }
1812:
1813:            public void emitCatchEnd() {
1814:                if (reachableHere()) {
1815:                    if (try_stack.saved_result != null)
1816:                        emitStore(try_stack.saved_result);
1817:                    if (try_stack.finally_subr != null)
1818:                        emitGoto(try_stack.finally_subr, 168); // jsr
1819:                    emitGoto(try_stack.end_label);
1820:                }
1821:                try_stack.try_type = null;
1822:            }
1823:
1824:            public void emitFinallyStart() {
1825:                emitTryEnd();
1826:                if (try_stack.try_type != null)
1827:                    emitCatchEnd();
1828:                readPC = PC;
1829:                SP = 0;
1830:                try_stack.end_pc = PC;
1831:
1832:                pushScope();
1833:                Type except_type = Type.pointer_type;
1834:                Variable except = addLocal(except_type);
1835:                emitCatchStart((Variable) null);
1836:                emitStore(except);
1837:                emitGoto(try_stack.finally_subr, 168); // jsr
1838:                emitLoad(except);
1839:                emitThrow();
1840:
1841:                try_stack.finally_subr.define(this );
1842:                Type ret_addr_type = Type.pointer_type;
1843:                try_stack.finally_ret_addr = addLocal(ret_addr_type);
1844:                pushType(ret_addr_type);
1845:                emitStore(try_stack.finally_ret_addr);
1846:            }
1847:
1848:            public void emitFinallyEnd() {
1849:                emitRet(try_stack.finally_ret_addr);
1850:                setUnreachable();
1851:                popScope();
1852:                try_stack.finally_subr = null;
1853:            }
1854:
1855:            public void emitTryCatchEnd() {
1856:                if (try_stack.finally_subr != null)
1857:                    emitFinallyEnd();
1858:                try_stack.end_label.define(this );
1859:                Variable[] vars = try_stack.savedStack;
1860:                if (vars != null) {
1861:                    for (int i = vars.length; --i >= 0;) {
1862:                        Variable v = vars[i];
1863:                        if (v != null) {
1864:                            emitLoad(v);
1865:                        }
1866:                    }
1867:                }
1868:                if (try_stack.saved_result != null)
1869:                    emitLoad(try_stack.saved_result);
1870:                if (try_stack.saved_result != null || vars != null)
1871:                    popScope();
1872:                try_stack = try_stack.previous;
1873:            }
1874:
1875:            public final boolean isInTry() {
1876:                // This also return true if we're in  a catch clause, but that is
1877:                // good enough for now.
1878:                return try_stack != null;
1879:            }
1880:
1881:            /** Compile a tail-call to position 0 of the current procewure.
1882:             * @param pop_args if true, copy argument registers (except this) from stack.
1883:             * @param scope Scope whose start we jump back to. */
1884:            public void emitTailCall(boolean pop_args, Scope scope) {
1885:                if (pop_args) {
1886:                    Method meth = getMethod();
1887:                    int arg_slots = ((meth.access_flags & Access.STATIC) != 0) ? 0
1888:                            : 1;
1889:                    for (int i = meth.arg_types.length; --i >= 0;)
1890:                        arg_slots += meth.arg_types[i].size > 4 ? 2 : 1;
1891:                    for (int i = meth.arg_types.length; --i >= 0;) {
1892:                        arg_slots -= meth.arg_types[i].size > 4 ? 2 : 1;
1893:                        emitStore(locals.used[arg_slots]);
1894:                    }
1895:                }
1896:                reserve(5);
1897:                int start_pc = scope.start_pc;
1898:                int delta = start_pc - PC;
1899:                if (delta < -32768) {
1900:                    put1(200); // goto_w
1901:                    put4(delta);
1902:                } else {
1903:                    put1(167); // goto
1904:                    put2(delta);
1905:                }
1906:                setUnreachable();
1907:            }
1908:
1909:            /* Make sure the label with oldest fixup is first in labels. */
1910:            void reorder_fixups() {
1911:                Label prev = null;
1912:                Label cur;
1913:                Label oldest = null;
1914:                Label oldest_prev = null;
1915:                int oldest_fixup = PC + 100;
1916:                for (cur = labels; cur != null; cur = cur.next) {
1917:                    if (cur.fixups != null && cur.fixups[0] < oldest_fixup) {
1918:                        oldest = cur;
1919:                        oldest_prev = prev;
1920:                        oldest_fixup = cur.fixups[0];
1921:                    }
1922:                    prev = cur;
1923:                }
1924:                if (oldest != labels && oldest != null) {
1925:                    oldest_prev.next = oldest.next;
1926:                    oldest.next = labels;
1927:                    labels = oldest;
1928:                }
1929:            }
1930:
1931:            public void finalize_labels() {
1932:                while (labels != null && labels.fixups != null)
1933:                    labels.emit_spring(this );
1934:                for (Label label = labels; label != null; label = label.next) {
1935:                    if (label.fixups != null || label.wide_fixups != null)
1936:                        throw new Error("undefined label");
1937:                }
1938:            }
1939:
1940:            public void assignConstants(ClassType cl) {
1941:                super .assignConstants(cl);
1942:                for (;;) {
1943:                    CodeFragment frag = fragments;
1944:                    if (frag == null)
1945:                        break;
1946:                    fragments = frag.next;
1947:                    frag.emit(this );
1948:                }
1949:                if (locals != null && locals.container == null
1950:                        && !locals.isEmpty())
1951:                    locals.addToFrontOf(this );
1952:                Attribute.assignConstants(this , cl);
1953:                finalize_labels();
1954:            }
1955:
1956:            public final int getLength() {
1957:                return 12 + getCodeLength() + 8 * exception_table_length
1958:                        + Attribute.getLengthAll(this );
1959:            }
1960:
1961:            public void write(DataOutputStream dstr) throws java.io.IOException {
1962:                dstr.writeShort(max_stack);
1963:                dstr.writeShort(max_locals);
1964:                dstr.writeInt(PC);
1965:                dstr.write(code, 0, PC);
1966:
1967:                dstr.writeShort(exception_table_length);
1968:                int count = exception_table_length;
1969:                for (int i = 0; --count >= 0; i += 4) {
1970:                    dstr.writeShort(exception_table[i]);
1971:                    dstr.writeShort(exception_table[i + 1]);
1972:                    dstr.writeShort(exception_table[i + 2]);
1973:                    dstr.writeShort(exception_table[i + 3]);
1974:                }
1975:
1976:                Attribute.writeAll(this , dstr);
1977:            }
1978:
1979:            public void print(ClassTypeWriter dst) {
1980:                dst.print("Attribute \"");
1981:                dst.print(getName());
1982:                dst.print("\", length:");
1983:                dst.print(getLength());
1984:                dst.print(", max_stack:");
1985:                dst.print(max_stack);
1986:                dst.print(", max_locals:");
1987:                dst.print(max_locals);
1988:                dst.print(", code_length:");
1989:                int length = getCodeLength();
1990:                dst.println(length);
1991:                disAssemble(dst, 0, length);
1992:                if (exception_table_length > 0) {
1993:                    dst.print("Exceptions (count: ");
1994:                    dst.print(exception_table_length);
1995:                    dst.println("):");
1996:                    int count = exception_table_length;
1997:                    for (int i = 0; --count >= 0; i += 4) {
1998:                        dst.print("  start: ");
1999:                        dst.print(exception_table[i] & 0xffff);
2000:                        dst.print(", end: ");
2001:                        dst.print(exception_table[i + 1] & 0xffff);
2002:                        dst.print(", handler: ");
2003:                        dst.print(exception_table[i + 2] & 0xffff);
2004:                        dst.print(", type: ");
2005:                        int catch_type_index = exception_table[i + 3] & 0xffff;
2006:                        if (catch_type_index == 0)
2007:                            dst.print("0 /* finally */");
2008:                        else {
2009:                            dst.printOptionalIndex(catch_type_index);
2010:                            dst.printConstantTersely(catch_type_index,
2011:                                    ConstantPool.CLASS);
2012:                        }
2013:                        dst.println();
2014:                    }
2015:                }
2016:                dst.printAttributes(this );
2017:            }
2018:
2019:            public void disAssemble(ClassTypeWriter dst, int offset, int length) {
2020:                boolean wide = false;
2021:                for (int i = offset; i < length;) {
2022:                    int oldpc = i++;
2023:                    int op = code[oldpc] & 0xff;
2024:                    String str = Integer.toString(oldpc);
2025:                    int printConstant = 0;
2026:                    int j = str.length();
2027:                    while (++j <= 3)
2028:                        dst.print(' ');
2029:                    dst.print(str);
2030:                    dst.print(": ");
2031:                    // We do a rough binary partition of the opcodes.
2032:                    if (op < 120) {
2033:                        if (op < 87) {
2034:                            if (op < 3)
2035:                                print("nop;aconst_null;iconst_m1;", op, dst);
2036:                            else if (op < 9) {
2037:                                dst.print("iconst_");
2038:                                dst.print(op - 3);
2039:                            } else if (op < 16) // op >= 9 [lconst_0] && op <= 15 [dconst_1]
2040:                            {
2041:                                char typ;
2042:                                if (op < 11) {
2043:                                    typ = 'l';
2044:                                    op -= 9;
2045:                                } else if (op < 14) {
2046:                                    typ = 'f';
2047:                                    op -= 11;
2048:                                } else {
2049:                                    typ = 'd';
2050:                                    op -= 14;
2051:                                }
2052:                                dst.print(typ);
2053:                                dst.print("const_");
2054:                                dst.print(op);
2055:                            } else if (op < 21) {
2056:                                if (op < 18) // op >= 16 [bipush] && op <= 17 [sipush]
2057:                                {
2058:                                    print("bipush ;sipush ;", op - 16, dst);
2059:                                    int constant;
2060:                                    if (op == 16)
2061:                                        constant = code[i++];
2062:                                    else {
2063:                                        constant = (short) readUnsignedShort(i);
2064:                                        i += 2;
2065:                                    }
2066:                                    dst.print(constant);
2067:                                } else // op >= 18 [ldc] && op <= 20 [ldc2_w]
2068:                                {
2069:                                    printConstant = op == 18 ? 1 : 2;
2070:                                    print("ldc;ldc_w;ldc2_w;", op - 18, dst);
2071:                                }
2072:                            } else // op >= 21 && op < 87
2073:                            {
2074:                                String load_or_store;
2075:                                if (op < 54) {
2076:                                    load_or_store = "load";
2077:                                } else {
2078:                                    load_or_store = "store";
2079:                                    op -= (54 - 21);
2080:                                }
2081:                                int index; // -2 if array op;  -1 if index follows
2082:                                if (op < 26) {
2083:                                    index = -1;
2084:                                    op -= 21;
2085:                                } else if (op < 46) {
2086:                                    op -= 26;
2087:                                    index = op % 4;
2088:                                    op >>= 2;
2089:                                } else {
2090:                                    index = -2;
2091:                                    op -= 46;
2092:                                }
2093:                                dst.print("ilfdabcs".charAt(op));
2094:                                if (index == -2)
2095:                                    dst.write('a');
2096:                                dst.print(load_or_store);
2097:                                if (index >= 0) {
2098:                                    dst.write('_');
2099:                                    dst.print(index);
2100:                                } else if (index == -1) {
2101:                                    if (wide) {
2102:                                        index = readUnsignedShort(i);
2103:                                        i += 2;
2104:                                    } else {
2105:                                        index = code[i] & 0xff;
2106:                                        i++;
2107:                                    }
2108:                                    wide = false;
2109:                                    dst.print(' ');
2110:                                    dst.print(index);
2111:                                }
2112:                            }
2113:                        } else // op >= 87 && op < 120
2114:                        {
2115:                            if (op < 96)
2116:                                print(
2117:                                        "pop;pop2;dup;dup_x1;dup_x2;dup2;dup2_x1;dup2_x2;swap;",
2118:                                        op - 87, dst);
2119:                            else // op >= 96 [iadd] && op <= 119 [dneg]
2120:                            {
2121:                                dst.print("ilfda".charAt((op - 96) % 4));
2122:                                print("add;sub;mul;div;rem;neg;",
2123:                                        (op - 96) >> 2, dst);
2124:                            }
2125:                        }
2126:                    } else // op >= 120
2127:                    {
2128:                        if (op < 170) {
2129:                            if (op < 132) // op >= 120 [ishl] && op <= 131 [lxor]
2130:                            {
2131:                                dst.print((op & 1) == 0 ? 'i' : 'l');
2132:                                print("shl;shr;ushr;and;or;xor;",
2133:                                        (op - 120) >> 1, dst);
2134:                            } else if (op == 132) // iinc
2135:                            {
2136:                                int var_index;
2137:                                int constant;
2138:                                dst.print("iinc");
2139:                                if (!wide) {
2140:                                    var_index = 0xff & code[i++];
2141:                                    constant = code[i++];
2142:                                } else {
2143:                                    var_index = readUnsignedShort(i);
2144:                                    i += 2;
2145:                                    constant = (short) readUnsignedShort(i);
2146:                                    i += 2;
2147:                                    wide = false;
2148:                                }
2149:                                dst.print(' ');
2150:                                dst.print(var_index);
2151:                                dst.print(' ');
2152:                                dst.print(constant);
2153:                            } else if (op < 148) // op >= 133 [i2l] && op <= 147 [i2s]
2154:                            {
2155:                                dst.print("ilfdi".charAt((op - 133) / 3));
2156:                                dst.print('2');
2157:                                dst.print("lfdifdildilfbcs".charAt(op - 133));
2158:                            } else if (op < 153) // op >= 148 [lcmp] && op <= 152 [dcmpg]
2159:                                print("lcmp;fcmpl;fcmpg;dcmpl;dcmpg;",
2160:                                        op - 148, dst);
2161:                            else if (op < 169) {
2162:                                if (op < 159) {
2163:                                    dst.print("if");
2164:                                    print("eq;ne;lt;ge;gt;le;", op - 153, dst);
2165:                                } else if (op < 167) {
2166:                                    if (op < 165) {
2167:                                        dst.print("if_icmp");
2168:                                    } else {
2169:                                        dst.print("if_acmp");
2170:                                        op -= 165 - 159;
2171:                                    }
2172:                                    print("eq;ne;lt;ge;gt;le;", op - 159, dst);
2173:                                } else
2174:                                    print("goto;jsr;", op - 167, dst);
2175:                                int delta = (short) readUnsignedShort(i);
2176:                                i += 2;
2177:                                dst.print(' ');
2178:                                dst.print(oldpc + delta);
2179:                            } else {
2180:                                int index;
2181:                                dst.print("ret ");
2182:                                if (wide) {
2183:                                    index = readUnsignedShort(i);
2184:                                    index += 2;
2185:                                } else {
2186:                                    index = code[i] & 0xff;
2187:                                    i++;
2188:                                }
2189:                                wide = false;
2190:                                dst.print(index);
2191:                            }
2192:                        } else {
2193:                            if (op < 172) //  [tableswitch] or [lookupswitch]
2194:                            {
2195:                                i = (i + 3) & ~3; // skip 0-3 byte padding.
2196:                                int code_offset = readInt(i);
2197:                                i += 4;
2198:                                if (op == 170) {
2199:                                    dst.print("tableswitch");
2200:                                    int low = readInt(i);
2201:                                    i += 4;
2202:                                    int high = readInt(i);
2203:                                    i += 4;
2204:                                    dst.print(" low: ");
2205:                                    dst.print(low);
2206:                                    dst.print(" high: ");
2207:                                    dst.print(high);
2208:                                    dst.print(" default: ");
2209:                                    dst.print(oldpc + code_offset);
2210:                                    for (; low <= high; low++) {
2211:                                        code_offset = readInt(i);
2212:                                        i += 4;
2213:                                        dst.println();
2214:                                        dst.print("  ");
2215:                                        dst.print(low);
2216:                                        dst.print(": ");
2217:                                        dst.print(oldpc + code_offset);
2218:                                    }
2219:                                } else {
2220:                                    dst.print("lookupswitch");
2221:                                    int npairs = readInt(i);
2222:                                    i += 4;
2223:                                    dst.print(" npairs: ");
2224:                                    dst.print(npairs);
2225:                                    dst.print(" default: ");
2226:                                    dst.print(oldpc + code_offset);
2227:                                    while (--npairs >= 0) {
2228:                                        int match = readInt(i);
2229:                                        i += 4;
2230:                                        code_offset = readInt(i);
2231:                                        i += 4;
2232:                                        dst.println();
2233:                                        dst.print("  ");
2234:                                        dst.print(match);
2235:                                        dst.print(": ");
2236:                                        dst.print(oldpc + code_offset);
2237:                                    }
2238:                                }
2239:                            } else if (op < 178) // op >= 172 [ireturn] && op <= 177 [return]
2240:                            {
2241:                                if (op < 177)
2242:                                    dst.print("ilfda".charAt(op - 172));
2243:                                dst.print("return");
2244:                            } else if (op < 182) // op >= 178 [getstatic] && op <= 181 [putfield]
2245:                            {
2246:                                print("getstatic;putstatic;getfield;putfield;",
2247:                                        op - 178, dst);
2248:                                printConstant = 2;
2249:                            } else if (op < 185) // op >= 182 && op <= 185 [invoke*]
2250:                            {
2251:                                dst.print("invoke");
2252:                                print("virtual;special;static;", op - 182, dst);
2253:                                printConstant = 2;
2254:                            } else if (op == 185) // invokeinterface
2255:                            {
2256:                                dst.print("invokeinterface (");
2257:                                int index = readUnsignedShort(i);
2258:                                i += 2;
2259:                                int args = 0xff & code[i];
2260:                                i += 2;
2261:                                dst.print(args + " args)");
2262:                                dst.printConstantOperand(index);
2263:                            } else if (op < 196) {
2264:                                print(
2265:                                        "186;new;newarray;anewarray;arraylength;athrow;checkcast;instanceof;monitorenter;monitorexit;",
2266:                                        op - 186, dst);
2267:                                if (op == 187 || op == 189 || op == 192
2268:                                        || op == 193)
2269:                                    printConstant = 2;
2270:                                else if (op == 188) // newarray
2271:                                {
2272:                                    int type = code[i++];
2273:                                    dst.print(' ');
2274:                                    if (type >= 4 && type <= 11)
2275:                                        print(
2276:                                                "boolean;char;float;double;byte;short;int;long;",
2277:                                                type - 4, dst);
2278:                                    else
2279:                                        dst.print(type);
2280:                                }
2281:
2282:                            } else if (op == 196) // wide
2283:                            {
2284:                                dst.print("wide");
2285:                                wide = true;
2286:                            } else if (op == 197) {
2287:                                dst.print("multianewarray");
2288:                                int index = readUnsignedShort(i);
2289:                                i += 2;
2290:                                dst.printConstantOperand(index);
2291:                                int dims = 0xff & code[i++];
2292:                                dst.print(' ');
2293:                                dst.print(dims);
2294:                            } else if (op < 200) {
2295:                                print("ifnull;ifnonnull;", op - 198, dst);
2296:                                int delta = (short) readUnsignedShort(i);
2297:                                i += 2;
2298:                                dst.print(' ');
2299:                                dst.print(oldpc + delta);
2300:                            } else if (op < 202) {
2301:                                print("goto_w;jsr_w;", op - 200, dst);
2302:                                int delta = readInt(i);
2303:                                i += 4;
2304:                                dst.print(' ');
2305:                                dst.print(oldpc + delta);
2306:                            } else
2307:                                dst.print(op);
2308:                        }
2309:                    }
2310:                    if (printConstant > 0) {
2311:                        int index;
2312:                        if (printConstant == 1)
2313:                            index = 0xff & code[i++];
2314:                        else {
2315:                            index = readUnsignedShort(i);
2316:                            i += 2;
2317:                        }
2318:                        dst.printConstantOperand(index);
2319:                    }
2320:                    dst.println();
2321:                }
2322:            }
2323:
2324:            private int readUnsignedShort(int offset) {
2325:                return ((0xff & code[offset]) << 8) | (0xff & code[offset + 1]);
2326:            }
2327:
2328:            private int readInt(int offset) {
2329:                return (readUnsignedShort(offset) << 16)
2330:                        | readUnsignedShort(offset + 2);
2331:            }
2332:
2333:            /*
2334:            public saveStack (ClassType into)
2335:            {
2336:              Field[] flds = new Field[SP];
2337:              while (SP > 0)
2338:                {
2339:            Field fld = ?;
2340:            emitStore(fld);
2341:            flds[SP...]
2342:                }
2343:            }
2344:             */
2345:
2346:            /* Print the i'th ';'-delimited substring of str on dst. */
2347:            private void print(String str, int i, PrintWriter dst) {
2348:                int last = 0;
2349:                int pos = -1;
2350:                for (; i >= 0; i--) {
2351:                    last = ++pos;
2352:                    pos = str.indexOf(';', last);
2353:                }
2354:                dst.write(str, last, pos - last);
2355:            }
2356:
2357:            /** Return an object encapsulating the type state of the JVM stack. */
2358:            public Type[] saveStackTypeState(boolean clear) {
2359:                if (SP == 0)
2360:                    return null;
2361:                Type[] typeState = new Type[SP];
2362:                System.arraycopy(stack_types, 0, typeState, 0, SP);
2363:                if (clear)
2364:                    SP = 0;
2365:                return typeState;
2366:            }
2367:
2368:            /** Restore a type state as saved by saveStackTypeState. */
2369:            public void restoreStackTypeState(Type[] save) {
2370:                if (save == null)
2371:                    SP = 0;
2372:                else {
2373:                    SP = save.length;
2374:                    System.arraycopy(save, 0, stack_types, 0, SP);
2375:                }
2376:            }
2377:
2378:            CodeFragment fragmentStack = null;
2379:
2380:            public void beginFragment(boolean isHandler) {
2381:                CodeFragment frag = new CodeFragment(this );
2382:                frag.next = fragmentStack;
2383:                fragmentStack = frag;
2384:                frag.length = PC;
2385:                frag.unreachable_save = unreachable_here;
2386:                unreachable_here = false;
2387:                if (isHandler)
2388:                    frag.handlerIndex = exception_table_length - 1;
2389:            }
2390:
2391:            public void endFragment() {
2392:                CodeFragment frag = fragmentStack;
2393:                fragmentStack = frag.next;
2394:
2395:                frag.next = fragments;
2396:                fragments = frag;
2397:                int startPC = frag.length;
2398:                frag.length = PC - startPC;
2399:                frag.insns = new byte[frag.length];
2400:                System.arraycopy(code, startPC, frag.insns, 0, frag.length);
2401:                PC = startPC;
2402:                unreachable_here = frag.unreachable_save;
2403:
2404:                if (lines != null) {
2405:                    int l = 2 * lines.linenumber_count;
2406:                    int j = l;
2407:                    short[] linenumbers = lines.linenumber_table;
2408:                    while (j > 0 && linenumbers[j - 2] >= startPC)
2409:                        j -= 2;
2410:                    l -= j;
2411:                    if (l > 0) {
2412:                        short[] fraglines = new short[l];
2413:                        for (int i = 0; i < l; i += 2) {
2414:                            fraglines[i] = (short) ((linenumbers[j + i] & 0xffff) - startPC);
2415:                            fraglines[i + 1] = linenumbers[j + i + 1];
2416:                        }
2417:                        frag.linenumbers = fraglines;
2418:                        lines.linenumber_count = j >> 1;
2419:                    }
2420:                }
2421:            }
2422:
2423:            /****************************************************************
2424:             * Postcondition
2425:             ****************************************************************/
2426:
2427:            public void preparePostcondition(Field assertionEnabled,
2428:                    boolean hasPostCond) {
2429:                this .assertionEnabled = assertionEnabled;
2430:                if (hasPostCond)
2431:                    postconditionStart = new Label(this );
2432:            }
2433:
2434:            public void startPrecondition() {
2435:                preconditionEnd = new Label(this );
2436:                ifAssertionsDisabledGoto(assertionEnabled, preconditionEnd);
2437:            }
2438:
2439:            public void endPrecondition() {
2440:                preconditionEnd.define(this );
2441:            }
2442:
2443:            public void startPostcondition() {
2444:                postconditionEnd = new Label(this );
2445:                postconditionStart.define(this );
2446:                Type type = getMethod().getReturnType();
2447:                if (!type.isVoid()) {
2448:                    // We expect the returned value on the stack.
2449:                    pushType(type);
2450:                    ifAssertionsDisabledGoto(assertionEnabled, postconditionEnd);
2451:                    resultVar = addLocal(type);
2452:                    emitStore(resultVar);
2453:                } else
2454:                    ifAssertionsDisabledGoto(assertionEnabled, postconditionEnd);
2455:            }
2456:
2457:            public void pushRetType() {
2458:                Type type = getMethod().getReturnType();
2459:                if (!type.isVoid())
2460:                    pushType(type);
2461:            }
2462:
2463:            public void endPostcondition() {
2464:                if (resultVar != null)
2465:                    loadResult();
2466:                postconditionEnd.define(this );
2467:                emitRealReturn();
2468:            }
2469:
2470:            public void loadResult() {
2471:                emitLoad(resultVar);
2472:            }
2473:
2474:            boolean checkPostcondition() {
2475:                if (postconditionStart == null)
2476:                    return false;
2477:                emitGoto(postconditionStart);
2478:                return true;
2479:            }
2480:
2481:            public void ifAssertionsDisabledGoto(Field assertionEnabled, Label l) {
2482:                emitGetStatic(assertionEnabled);
2483:                emitGotoIfIntEqZero(l);
2484:            }
2485:
2486:            private Label postconditionStart, postconditionEnd,
2487:                    preconditionEnd;
2488:            private Variable resultVar;
2489:            private Field assertionEnabled;
2490:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.