Source Code Cross Referenced for CodeArray.java in  » Database-DBMS » db4o-6.4 » EDU » purdue » cs » bloat » editor » 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 » Database DBMS » db4o 6.4 » EDU.purdue.cs.bloat.editor 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* Copyright (C) 2004 - 2007  db4objects Inc.  http://www.db4o.com
0002:
0003:        This file is part of the db4o open source object database.
0004:
0005:        db4o is free software; you can redistribute it and/or modify it under
0006:        the terms of version 2 of the GNU General Public License as published
0007:        by the Free Software Foundation and as clarified by db4objects' GPL 
0008:        interpretation policy, available at
0009:        http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
0010:        Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
0011:        Suite 350, San Mateo, CA 94403, USA.
0012:
0013:        db4o is distributed in the hope that it will be useful, but WITHOUT ANY
0014:        WARRANTY; without even the implied warranty of MERCHANTABILITY or
0015:        FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0016:        for more details.
0017:
0018:        You should have received a copy of the GNU General Public License along
0019:        with this program; if not, write to the Free Software Foundation, Inc.,
0020:        59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. */
0021:        package EDU.purdue.cs.bloat.editor;
0022:
0023:        import java.util.*;
0024:
0025:        import EDU.purdue.cs.bloat.reflect.*;
0026:        import EDU.purdue.cs.bloat.util.*;
0027:
0028:        /**
0029:         * CodeArray converts an array of Instructions into an array of bytes suitable
0030:         * for saving to a <tt>MethodInfo</tt> with <tt>setCode</tt>.
0031:         * 
0032:         * <p>
0033:         * 
0034:         * The byte array is returned by calling the <tt>array</tt> method.
0035:         * 
0036:         * <p>
0037:         * 
0038:         * This code assumes no branch will be longer than 65536 bytes.
0039:         * 
0040:         * @see Instruction
0041:         * @see MethodInfo
0042:         * @see MethodInfo#setCode
0043:         * 
0044:         * @author Nate Nystrom (<a
0045:         *         href="mailto:nystrom@cs.purdue.edu">nystrom@cs.purdue.edu</a>)
0046:         */
0047:        public class CodeArray implements  InstructionVisitor, Opcode {
0048:            public static boolean DEBUG = Boolean.getBoolean("CodeArray.DEBUG");
0049:
0050:            private ByteCell codeTail; // Linked list of ByteCells representing code
0051:
0052:            private int codeLength; // Number of bytes in method
0053:
0054:            private Map branches;
0055:
0056:            private Map longBranches;
0057:
0058:            private Map branchInsts;
0059:
0060:            private Map labels; // Labels mapped to their offsets
0061:
0062:            private int lastInst; // Offset of last (most recent) instrucion
0063:
0064:            private int maxStack; // Max stack height
0065:
0066:            private int stackHeight; // Current stack height
0067:
0068:            private int maxLocals; // Max number of local variables
0069:
0070:            private ConstantPool constants;
0071:
0072:            private MethodEditor method;
0073:
0074:            private boolean longBranch; // Do we use long (wide) jumps?
0075:
0076:            private List insts;
0077:
0078:            /**
0079:             * Create the byte array for a method.
0080:             * 
0081:             * @param method
0082:             *            The method being edited.
0083:             * @param constants
0084:             *            The constant pool of the class.
0085:             * @param insts
0086:             *            A List of Instructions and Labels to convert to a byte array.
0087:             * @see MethodEditor
0088:             * @see ConstantPool
0089:             * @see Instruction
0090:             * @see Label
0091:             */
0092:            public CodeArray(final MethodEditor method,
0093:                    final ConstantPool constants, final List insts) {
0094:                this .constants = constants;
0095:                this .method = method;
0096:                this .insts = insts;
0097:                this .maxStack = 0;
0098:                this .maxLocals = 0;
0099:
0100:                longBranch = false;
0101:                buildCode();
0102:            }
0103:
0104:            /**
0105:             * Examine the method's Labels and Instructions. Keep track of such things
0106:             * as the height of the stack at each instruction and to where subroutines
0107:             * return. The ultimate goal is to compute the max stack height of this
0108:             * method. This computation is complicated by subroutines that may be
0109:             * invoked at a variety of stack heights.
0110:             */
0111:            private void buildCode() {
0112:                codeTail = null;
0113:                codeLength = 0;
0114:                branches = new HashMap();
0115:                longBranches = new HashMap();
0116:                branchInsts = new HashMap();
0117:                labels = new HashMap();
0118:
0119:                // We need at least enought locals to store the parameters
0120:                maxLocals = method.type().stackHeight();
0121:
0122:                if (!method.isStatic()) {
0123:                    // One more for the this pointer
0124:                    maxLocals++;
0125:                }
0126:
0127:                stackHeight = 0;
0128:
0129:                final Map labelPos = new HashMap(); // Maps Labels to their code offsets
0130:                final int[] heights = new int[insts.size()]; // Stack height at each
0131:                // inst
0132:
0133:                // Maps Labels that begin jsrs to their return targets. Maps ret
0134:                // instructions to the subroutine from which they return.
0135:                final Map retTargets = new HashMap();
0136:                final Map retInsts = new HashMap();
0137:
0138:                // Print the code we're dealing with
0139:                if (CodeArray.DEBUG) {
0140:                    System.out.println("Building code for "
0141:                            + method.declaringClass().name() + "."
0142:                            + method.name());
0143:                    final Iterator iter = insts.iterator();
0144:                    while (iter.hasNext()) {
0145:                        final Object o = iter.next();
0146:                        System.out.println("  " + o);
0147:                    }
0148:                }
0149:
0150:                // Build the bytecode array, assuming each basic block begins with
0151:                // stack height 0. We'll fix up the heights later.
0152:                final Iterator iter = insts.iterator();
0153:                int i = 0; // Which instruction are we at?
0154:                while (iter.hasNext()) {
0155:                    final Object ce = iter.next();
0156:
0157:                    if (ce instanceof  Label) {
0158:                        final Label label = (Label) ce;
0159:
0160:                        // A Label starts a new basic block. Reset the stack height.
0161:
0162:                        stackHeight = 0;
0163:                        labelPos.put(label, new Integer(i));
0164:
0165:                        addLabel(label);
0166:                        heights[i++] = stackHeight;
0167:
0168:                        // If this label starts a subroutine (i.e. is the target of
0169:                        // jsr instruction), then make not of it.
0170:                        if (retTargets.containsKey(label)) {
0171:                        }
0172:
0173:                    } else if (ce instanceof  Instruction) {
0174:                        final Instruction inst = (Instruction) ce;
0175:
0176:                        // Visit this instruction to compute the current stack height
0177:                        inst.visit(this );
0178:
0179:                        if (inst.isJsr()) {
0180:                            // Make sure that the jsr is not the last instruction in the
0181:                            // method. If it was, where would we return to? Make note
0182:                            // of the return target (the Label following the jsr).
0183:
0184:                            heights[i++] = stackHeight;
0185:
0186:                            Assert.isTrue(iter.hasNext(), inst
0187:                                    + " found at end of method");
0188:
0189:                            final Object x = iter.next();
0190:
0191:                            Assert.isTrue(x instanceof  Label, inst
0192:                                    + " not followed by label");
0193:
0194:                            final Label sub = (Label) inst.operand();
0195:                            final Label target = (Label) x;
0196:
0197:                            // Maintain a mapping between a subroutine (the Label that
0198:                            // begins it) and all return targets.
0199:                            Set targets = (Set) retTargets.get(sub);
0200:                            if (targets == null) {
0201:                                targets = new HashSet();
0202:                                retTargets.put(sub, targets);
0203:                            }
0204:                            targets.add(target);
0205:
0206:                            stackHeight = 0;
0207:                            labelPos.put(target, new Integer(i));
0208:
0209:                            addLabel(target);
0210:                            heights[i++] = stackHeight;
0211:
0212:                        } else {
0213:                            heights[i++] = stackHeight;
0214:                        }
0215:
0216:                    } else {
0217:                        // Something bad in instruction list
0218:                        throw new IllegalArgumentException();
0219:                    }
0220:                }
0221:
0222:                // Sorry, but we have to make another forward pass over some of
0223:                // the code to determine the subroutine from which a given ret
0224:                // instruction returns.
0225:                final Iterator subLabels = retTargets.keySet().iterator();
0226:                while (subLabels.hasNext()) {
0227:                    final Label subLabel = (Label) subLabels.next();
0228:                    final int pos = insts.indexOf(subLabel);
0229:                    Assert
0230:                            .isTrue(pos != -1, "Label " + subLabel
0231:                                    + " not found");
0232:                    boolean foundRet = false;
0233:                    final ListIterator liter = insts.listIterator(pos);
0234:                    while (liter.hasNext()) {
0235:                        final Object o = liter.next();
0236:                        if (o instanceof  Instruction) {
0237:                            final Instruction inst = (Instruction) o;
0238:                            if (inst.isRet()) {
0239:                                retInsts.put(inst, subLabel);
0240:                                foundRet = true;
0241:                                break;
0242:                            }
0243:                        }
0244:                    }
0245:                    Assert
0246:                            .isTrue(foundRet, "No ret for subroutine "
0247:                                    + subLabel);
0248:                }
0249:
0250:                if (CodeArray.DEBUG) {
0251:                    // Print subroutine to return target mapping
0252:                    System.out.println("Subroutines and return targets:");
0253:                    final Iterator subs = retTargets.keySet().iterator();
0254:                    while (subs.hasNext()) {
0255:                        final Label sub = (Label) subs.next();
0256:                        System.out.print("  " + sub + ": ");
0257:                        final Set s = (Set) retTargets.get(sub);
0258:                        Assert
0259:                                .isTrue(s != null, "No return targets for "
0260:                                        + sub);
0261:                        final Iterator rets = s.iterator();
0262:                        while (rets.hasNext()) {
0263:                            final Label ret = (Label) rets.next();
0264:                            System.out.print(ret.toString());
0265:                            if (rets.hasNext()) {
0266:                                System.out.print(", ");
0267:                            }
0268:                        }
0269:                        System.out.println("");
0270:                    }
0271:                }
0272:
0273:                // Fix up the stack heights by propagating the heights at each catch
0274:                // and each branch to their targets. Visit the blocks
0275:                // depth-first. Remember that the classfile requires the maximum
0276:                // stack height. I would assume that is why we do all of this
0277:                // stack height calculation stuff.
0278:
0279:                final Set visited = new HashSet(); // Labels that we've seen
0280:                final Stack stack = new Stack(); // Stack of HeightRecords
0281:                Label label;
0282:
0283:                // Start with the first Label
0284:                if (insts.size() > 0) {
0285:                    Assert.isTrue((insts.get(0) instanceof  Label),
0286:                            "A method must begin with a Label, not "
0287:                                    + insts.get(0));
0288:                    label = (Label) insts.get(0);
0289:                    visited.add(label);
0290:                    stack.push(new HeightRecord(label, 0));
0291:                }
0292:
0293:                // Also examine each exception handler. Recall that the exception
0294:                // object is implicitly pushed on the stack. So, the HeightRecord
0295:                // initially has height 1.
0296:                final Iterator e = method.tryCatches().iterator();
0297:                while (e.hasNext()) {
0298:                    final TryCatch tc = (TryCatch) e.next();
0299:                    visited.add(tc.handler());
0300:                    stack.push(new HeightRecord(tc.handler(), 1));
0301:                }
0302:
0303:                // Examine the HeightRecords on the stack. Make sure that the
0304:                // stack height has not exceeded 256. If the height at a given
0305:                // label has changed since we last visited it, then propagate this
0306:                // change to labels following the block begun by the label in
0307:                // question.
0308:                while (!stack.isEmpty()) {
0309:                    final HeightRecord h = (HeightRecord) stack.pop();
0310:
0311:                    Assert.isTrue(h.height < 256, "Stack height of " + h.height
0312:                            + " reached. " + h.label + " ("
0313:                            + labelPos.get(h.label) + ")");
0314:
0315:                    if (ClassEditor.DEBUG || CodeArray.DEBUG) {
0316:                        System.out.println(h.label + " has height " + h.height);
0317:                    }
0318:
0319:                    Integer labelIndex = (Integer) labelPos.get(h.label);
0320:                    Assert.isTrue(labelIndex != null, "Index of " + h.label
0321:                            + " not found");
0322:
0323:                    final int start = labelIndex.intValue();
0324:                    int diff = h.height - heights[start];
0325:
0326:                    // Propagate the change in height to the next branch.
0327:                    // Then push the branch targets.
0328:                    if (ClassEditor.DEBUG) {
0329:                        /*
0330:                         * System.out.println(" " + h.label + ": change " +
0331:                         * heights[start] + " to " + h.height);
0332:                         */
0333:                    }
0334:
0335:                    heights[start] = h.height;
0336:
0337:                    final ListIterator blockIter = insts
0338:                            .listIterator(start + 1);
0339:                    i = start;
0340:
0341:                    // Examine the instructions following the label
0342:                    while (blockIter.hasNext()) {
0343:                        final Object ce = blockIter.next();
0344:
0345:                        i++;
0346:
0347:                        if (ce instanceof  Instruction) {
0348:                            final Instruction inst = (Instruction) ce;
0349:
0350:                            if (inst.isReturn() || inst.isThrow()) {
0351:                                // The method terminates. The stack is popped empty.
0352:                                heights[i] = 0;
0353:
0354:                                if (ClassEditor.DEBUG || CodeArray.DEBUG) {
0355:                                    System.out.println("  " + heights[i] + ") "
0356:                                            + inst);
0357:                                }
0358:
0359:                                // Consider next HeightRecord on stack.
0360:                                break;
0361:
0362:                            } else if (inst.isConditionalJump()) {
0363:                                // If the stack height at this Label has changed since
0364:                                // we
0365:                                // last saw it or if we have not processed the target of
0366:                                // the jump, add a new HeightRecord for the target
0367:                                // Label.
0368:
0369:                                heights[i] += diff;
0370:
0371:                                if (ClassEditor.DEBUG || CodeArray.DEBUG) {
0372:                                    System.out.println("  " + heights[i] + ") "
0373:                                            + inst);
0374:                                }
0375:
0376:                                label = (Label) inst.operand();
0377:
0378:                                if ((diff > 0) || !visited.contains(label)) {
0379:                                    visited.add(label);
0380:                                    stack.push(new HeightRecord(label,
0381:                                            heights[i]));
0382:                                }
0383:
0384:                                // Fall through. That is, process the instruction after
0385:                                // the conditional jump. Remember that the code is in
0386:                                // trace order so the false block (which is the next
0387:                                // block
0388:                                // in a depth first traversal) follows. The height of
0389:                                // the
0390:                                // stack won't change when we fall through.
0391:
0392:                            } else if (inst.isGoto() || inst.isJsr()) {
0393:                                // Once again, if we have already visited the target
0394:                                // block, add a HeightRecord to the stack.
0395:
0396:                                heights[i] += diff;
0397:
0398:                                if (ClassEditor.DEBUG || CodeArray.DEBUG) {
0399:                                    System.out.println("  " + heights[i] + ") "
0400:                                            + inst);
0401:                                }
0402:
0403:                                label = (Label) inst.operand();
0404:
0405:                                if ((diff > 0) || !visited.contains(label)) {
0406:                                    visited.add(label);
0407:                                    stack.push(new HeightRecord(label,
0408:                                            heights[i]));
0409:                                }
0410:
0411:                                // Deal with the next HeightRecord on the stack.
0412:                                break;
0413:
0414:                            } else if (inst.isRet()) {
0415:                                // Process any unvisited return targets (of the current
0416:                                // jsr) or those whose current height is less than the
0417:                                // height at this return instruction.
0418:
0419:                                heights[i] += diff;
0420:
0421:                                if (ClassEditor.DEBUG || CodeArray.DEBUG) {
0422:                                    System.out.println("  " + heights[i] + ") "
0423:                                            + inst);
0424:                                }
0425:
0426:                                final Label subLabel = (Label) retInsts
0427:                                        .get(inst);
0428:                                Assert.isTrue(subLabel != null,
0429:                                        "Not inside a subroutine at " + inst);
0430:
0431:                                final Set targets = (Set) retTargets
0432:                                        .get(subLabel);
0433:                                Assert.isTrue(targets != null, "Subroutine "
0434:                                        + subLabel + " has no return targets");
0435:
0436:                                if (ClassEditor.DEBUG || CodeArray.DEBUG) {
0437:                                    System.out.println("    Returning from: "
0438:                                            + subLabel);
0439:                                }
0440:
0441:                                final Iterator retIter = targets.iterator();
0442:
0443:                                while (retIter.hasNext()) {
0444:                                    label = (Label) retIter.next();
0445:
0446:                                    labelIndex = (Integer) labelPos.get(label);
0447:                                    Assert.isTrue(labelIndex != null,
0448:                                            "Index of " + label + " not found");
0449:
0450:                                    final int idx = labelIndex.intValue();
0451:
0452:                                    if ((heights[idx] < heights[i])
0453:                                            || !visited.contains(label)) {
0454:                                        visited.add(label);
0455:                                        stack.push(new HeightRecord(label,
0456:                                                heights[i]));
0457:                                    }
0458:                                }
0459:
0460:                                break;
0461:
0462:                            } else if (inst.isSwitch()) {
0463:                                // Visit each unvisited switch target if it increases
0464:                                // the
0465:                                // stack height
0466:
0467:                                // If the height at this Label has changed since it was
0468:                                // last visited, process each target Label. Otherwise,
0469:                                // only process unvisited Labels.
0470:
0471:                                heights[i] += diff;
0472:
0473:                                if (ClassEditor.DEBUG || CodeArray.DEBUG) {
0474:                                    System.out.println("  " + heights[i] + ") "
0475:                                            + inst);
0476:                                }
0477:
0478:                                // A switch.
0479:                                final Switch sw = (Switch) inst.operand();
0480:
0481:                                label = sw.defaultTarget();
0482:
0483:                                if ((diff > 0) || !visited.contains(label)) {
0484:                                    visited.add(label);
0485:                                    stack.push(new HeightRecord(label,
0486:                                            heights[i]));
0487:                                }
0488:
0489:                                final Label[] targets = sw.targets();
0490:
0491:                                for (int j = 0; j < targets.length; j++) {
0492:                                    label = targets[j];
0493:                                    if ((diff > 0) || !visited.contains(label)) {
0494:                                        visited.add(label);
0495:                                        stack.push(new HeightRecord(label,
0496:                                                heights[i]));
0497:                                    }
0498:                                }
0499:
0500:                                break;
0501:
0502:                            } else {
0503:                                // No other blocks to visit. Just adjust the height.
0504:
0505:                                heights[i] += diff;
0506:
0507:                                if (ClassEditor.DEBUG || CodeArray.DEBUG) {
0508:                                    System.out.println("  " + heights[i] + ") "
0509:                                            + inst);
0510:                                }
0511:                            }
0512:
0513:                        } else if (ce instanceof  Label) {
0514:                            // We've hit the next block. Update the stack height.
0515:                            // Process this next block if has not been visited or its
0516:                            // current height is different from the previous
0517:                            // instruction.
0518:
0519:                            label = (Label) ce;
0520:
0521:                            diff = heights[i - 1] - heights[i];
0522:
0523:                            if ((diff > 0) || !visited.contains(label)) {
0524:                                visited.add(label);
0525:                                heights[i] = heights[i - 1];
0526:                            }
0527:
0528:                            if (ClassEditor.DEBUG || CodeArray.DEBUG) {
0529:                                System.out.println("  " + heights[i] + ") "
0530:                                        + label);
0531:                            }
0532:                        }
0533:                    }
0534:                }
0535:
0536:                // Find the maximum stack height.
0537:                maxStack = 0;
0538:
0539:                for (i = 0; i < heights.length; i++) {
0540:                    final int h = heights[i];
0541:
0542:                    if (h > maxStack) {
0543:                        maxStack = h;
0544:                    }
0545:                }
0546:            }
0547:
0548:            /**
0549:             * Returns the maximum number of local variables used by this method.
0550:             */
0551:            public int maxLocals() {
0552:                return maxLocals;
0553:            }
0554:
0555:            /**
0556:             * Returns the maximum height of the stack at any point in this method.
0557:             */
0558:            public int maxStack() {
0559:                return maxStack;
0560:            }
0561:
0562:            /**
0563:             * Returns the index in the byte array of the given label.
0564:             */
0565:            public int labelIndex(final Label label) {
0566:                final Integer i = (Integer) labels.get(label);
0567:
0568:                if (i != null) {
0569:                    return i.intValue();
0570:                }
0571:
0572:                throw new IllegalArgumentException("Label " + label
0573:                        + " not found");
0574:            }
0575:
0576:            /**
0577:             * Returns the byte array after resolving branches.
0578:             */
0579:            public byte[] array() {
0580:                if (branches.size() > 0) {
0581:                    if (!longBranch && (codeLength >= 0x10000)) {
0582:                        longBranch = true;
0583:                        buildCode();
0584:                    }
0585:                }
0586:
0587:                final byte[] c = new byte[codeLength];
0588:                int i = codeLength;
0589:
0590:                for (ByteCell p = codeTail; p != null; p = p.prev) {
0591:                    c[--i] = p.value;
0592:                }
0593:
0594:                Iterator e;
0595:
0596:                e = branches.keySet().iterator();
0597:
0598:                while (e.hasNext()) {
0599:                    final Integer branch = (Integer) e.next();
0600:                    final int branchIndex = branch.intValue();
0601:
0602:                    final Integer inst = (Integer) branchInsts.get(branch);
0603:                    final int instIndex = inst.intValue();
0604:
0605:                    final Label label = (Label) branches.get(branch);
0606:                    final Integer target = (Integer) labels.get(label);
0607:
0608:                    Assert.isTrue(target != null, "Index of " + label
0609:                            + " not found");
0610:
0611:                    int diff = target.intValue() - instIndex;
0612:
0613:                    Assert.isTrue((-diff < 0x10000) && (diff < 0x10000),
0614:                            "Branch offset too large: " + diff);
0615:
0616:                    c[branchIndex] = (byte) ((diff >>> 8) & 0xff);
0617:                    c[branchIndex + 1] = (byte) (diff & 0xff);
0618:                }
0619:
0620:                e = longBranches.keySet().iterator();
0621:
0622:                while (e.hasNext()) {
0623:                    final Integer branch = (Integer) e.next();
0624:                    final int branchIndex = branch.intValue();
0625:
0626:                    final Integer inst = (Integer) branchInsts.get(branch);
0627:                    final int instIndex = inst.intValue();
0628:
0629:                    final Label label = (Label) longBranches.get(branch);
0630:                    final Integer target = (Integer) labels.get(label);
0631:
0632:                    final int diff = target.intValue() - instIndex;
0633:
0634:                    c[branchIndex] = (byte) ((diff >>> 24) & 0xff);
0635:                    c[branchIndex + 1] = (byte) ((diff >>> 16) & 0xff);
0636:                    c[branchIndex + 2] = (byte) ((diff >>> 8) & 0xff);
0637:                    c[branchIndex + 3] = (byte) (diff & 0xff);
0638:                }
0639:
0640:                return c;
0641:            }
0642:
0643:            /**
0644:             * Makes note of a label.
0645:             */
0646:            public void addLabel(final Label label) {
0647:                if (ClassEditor.DEBUG || CodeArray.DEBUG) {
0648:                    System.out.println("    " + codeLength + ": " + "label "
0649:                            + label);
0650:                }
0651:
0652:                labels.put(label, new Integer(codeLength));
0653:            }
0654:
0655:            /**
0656:             * Adds a 4-byte branch to a given label. The branch is from the index of
0657:             * the last opcode added.
0658:             */
0659:            public void addLongBranch(final Label label) {
0660:                if (ClassEditor.DEBUG || CodeArray.DEBUG) {
0661:                    System.out.println("    " + codeLength + ": "
0662:                            + "long branch to " + label);
0663:                }
0664:
0665:                branchInsts.put(new Integer(codeLength), new Integer(lastInst));
0666:                longBranches.put(new Integer(codeLength), label);
0667:                addByte(0);
0668:                addByte(0);
0669:                addByte(0);
0670:                addByte(0);
0671:            }
0672:
0673:            /**
0674:             * Adds a 2-byte branch to a given label. The branch is from the index of
0675:             * the last opcode added.
0676:             */
0677:            public void addBranch(final Label label) {
0678:                if (ClassEditor.DEBUG || CodeArray.DEBUG) {
0679:                    System.out.println("    " + codeLength + ": "
0680:                            + "branch to " + label);
0681:                }
0682:
0683:                branchInsts.put(new Integer(codeLength), new Integer(lastInst));
0684:                branches.put(new Integer(codeLength), label);
0685:                addByte(0);
0686:                addByte(0);
0687:            }
0688:
0689:            /**
0690:             * Add an opcode to the byte array, adjusting for 4-byte alignment for
0691:             * switch instructions and saving the index for calculating branches.
0692:             * 
0693:             * @param opcode
0694:             *            The opcode.
0695:             * @see Opcode
0696:             */
0697:            public void addOpcode(final int opcode) {
0698:                if (ClassEditor.DEBUG || CodeArray.DEBUG) {
0699:                    System.out.println("    " + codeLength + ": " + "opcode "
0700:                            + Opcode.opcNames[opcode]);
0701:                }
0702:
0703:                lastInst = codeLength;
0704:
0705:                addByte(opcode);
0706:
0707:                if ((opcode == Opcode.opc_tableswitch)
0708:                        || (opcode == Opcode.opc_lookupswitch)) {
0709:                    // Switch instructions are followed by padding so that table
0710:                    // starts on a 4-byte boundary.
0711:                    while (codeLength % 4 != 0) {
0712:                        addByte(0);
0713:                    }
0714:                }
0715:            }
0716:
0717:            /**
0718:             * Adds a single byte to the array.
0719:             */
0720:            public void addByte(final int i) {
0721:                if (ClassEditor.DEBUG) {
0722:                    System.out
0723:                            .println("    " + codeLength + ": " + "byte " + i);
0724:                }
0725:
0726:                // The bytecode array is represented as a linked list of
0727:                // ByteCells. This method creates a new ByteCell and appends it
0728:                // to the linked list.
0729:
0730:                final ByteCell p = new ByteCell();
0731:                p.value = (byte) (i & 0xff);
0732:                p.prev = codeTail;
0733:                codeTail = p;
0734:                codeLength++;
0735:            }
0736:
0737:            /**
0738:             * Adds a 2-byte short to the array, high byte first.
0739:             */
0740:            public void addShort(final int i) {
0741:                if (ClassEditor.DEBUG) {
0742:                    System.out.println("    " + codeLength + ": " + "short "
0743:                            + i);
0744:                }
0745:
0746:                addByte(i >>> 8);
0747:                addByte(i);
0748:            }
0749:
0750:            /**
0751:             * Adds a 4-byte int to the array, high byte first.
0752:             */
0753:            public void addInt(final int i) {
0754:                if (ClassEditor.DEBUG) {
0755:                    System.out.println("    " + codeLength + ": " + "int " + i);
0756:                }
0757:
0758:                addByte(i >>> 24);
0759:                addByte(i >>> 16);
0760:                addByte(i >>> 8);
0761:                addByte(i);
0762:            }
0763:
0764:            public void visit_nop(final Instruction inst) {
0765:                // If it must have been put there for a reason.
0766:                addOpcode(Opcode.opc_nop);
0767:                stackHeight += 0;
0768:            }
0769:
0770:            /*
0771:             * Does pretty much what you'd expect. Examines the instruction's operand to
0772:             * determine if one of the special constant opcodes (e.g. iconst_1) can be
0773:             * used. Adds the most appropriate instruction.
0774:             */
0775:            public void visit_ldc(final Instruction inst) {
0776:                final Object operand = inst.operand();
0777:
0778:                if (operand == null) {
0779:                    addOpcode(Opcode.opc_aconst_null);
0780:                    stackHeight++;
0781:
0782:                } else if (operand instanceof  Integer) {
0783:                    final int v = ((Integer) operand).intValue();
0784:
0785:                    switch (v) {
0786:                    case -1:
0787:                        addOpcode(Opcode.opc_iconst_m1);
0788:                        break;
0789:                    case 0:
0790:                        addOpcode(Opcode.opc_iconst_0);
0791:                        break;
0792:                    case 1:
0793:                        addOpcode(Opcode.opc_iconst_1);
0794:                        break;
0795:                    case 2:
0796:                        addOpcode(Opcode.opc_iconst_2);
0797:                        break;
0798:                    case 3:
0799:                        addOpcode(Opcode.opc_iconst_3);
0800:                        break;
0801:                    case 4:
0802:                        addOpcode(Opcode.opc_iconst_4);
0803:                        break;
0804:                    case 5:
0805:                        addOpcode(Opcode.opc_iconst_5);
0806:                        break;
0807:                    default: {
0808:                        if ((byte) v == v) {
0809:                            addOpcode(Opcode.opc_bipush);
0810:                            addByte(v);
0811:                        } else if ((short) v == v) {
0812:                            addOpcode(Opcode.opc_sipush);
0813:                            addShort(v);
0814:                        } else {
0815:                            final int index = constants.addConstant(
0816:                                    Constant.INTEGER, operand);
0817:                            if (index < 256) {
0818:                                addOpcode(Opcode.opc_ldc);
0819:                                addByte(index);
0820:                            } else {
0821:                                addOpcode(Opcode.opc_ldc_w);
0822:                                addShort(index);
0823:                            }
0824:                        }
0825:                        break;
0826:                    }
0827:                    }
0828:
0829:                    stackHeight++;
0830:
0831:                } else if (operand instanceof  Float) {
0832:                    final float v = ((Float) operand).floatValue();
0833:
0834:                    if (v == 0.0F) {
0835:                        addOpcode(Opcode.opc_fconst_0);
0836:                    } else if (v == 1.0F) {
0837:                        addOpcode(Opcode.opc_fconst_1);
0838:                    } else if (v == 2.0F) {
0839:                        addOpcode(Opcode.opc_fconst_2);
0840:                    } else {
0841:                        final int index = constants.addConstant(Constant.FLOAT,
0842:                                operand);
0843:                        if (index < 256) {
0844:                            addOpcode(Opcode.opc_ldc);
0845:                            addByte(index);
0846:                        } else {
0847:                            addOpcode(Opcode.opc_ldc_w);
0848:                            addShort(index);
0849:                        }
0850:                    }
0851:
0852:                    stackHeight++;
0853:
0854:                } else if (operand instanceof  Long) {
0855:                    final long v = ((Long) operand).longValue();
0856:
0857:                    if (v == 0) {
0858:                        addOpcode(Opcode.opc_lconst_0);
0859:                    } else if (v == 1) {
0860:                        addOpcode(Opcode.opc_lconst_1);
0861:                    } else {
0862:                        final int index = constants.addConstant(Constant.LONG,
0863:                                operand);
0864:                        addOpcode(Opcode.opc_ldc2_w);
0865:                        addShort(index);
0866:                    }
0867:
0868:                    stackHeight += 2;
0869:
0870:                } else if (operand instanceof  Double) {
0871:                    final double v = ((Double) operand).doubleValue();
0872:
0873:                    if (v == 0.0) {
0874:                        addOpcode(Opcode.opc_dconst_0);
0875:                    } else if (v == 1.0) {
0876:                        addOpcode(Opcode.opc_dconst_1);
0877:                    } else {
0878:                        final int index = constants.addConstant(
0879:                                Constant.DOUBLE, operand);
0880:                        addOpcode(Opcode.opc_ldc2_w);
0881:                        addShort(index);
0882:                    }
0883:
0884:                    stackHeight += 2;
0885:
0886:                } else if (operand instanceof  String) {
0887:                    final int index = constants.addConstant(Constant.STRING,
0888:                            operand);
0889:
0890:                    if (index < 256) {
0891:                        addOpcode(Opcode.opc_ldc);
0892:                        addByte(index);
0893:                    } else {
0894:                        addOpcode(Opcode.opc_ldc_w);
0895:                        addShort(index);
0896:                    }
0897:
0898:                    stackHeight++;
0899:                } else {
0900:                    throw new RuntimeException();
0901:                }
0902:            }
0903:
0904:            /*
0905:             * Tries to use the shorter iload_x instructions.
0906:             */
0907:            public void visit_iload(final Instruction inst) {
0908:                final int index = ((LocalVariable) inst.operand()).index();
0909:
0910:                if (index + 1 > maxLocals) {
0911:                    maxLocals = index + 1;
0912:                }
0913:
0914:                if (inst.useSlow()) {
0915:                    if (index < 256) {
0916:                        addOpcode(Opcode.opc_iload);
0917:                        addByte(index);
0918:                    } else {
0919:                        addOpcode(Opcode.opc_wide);
0920:                        addByte(Opcode.opc_iload);
0921:                        addShort(index);
0922:                    }
0923:                    stackHeight++;
0924:                    return;
0925:                }
0926:
0927:                switch (index) {
0928:                case 0:
0929:                    addOpcode(Opcode.opc_iload_0);
0930:                    break;
0931:                case 1:
0932:                    addOpcode(Opcode.opc_iload_1);
0933:                    break;
0934:                case 2:
0935:                    addOpcode(Opcode.opc_iload_2);
0936:                    break;
0937:                case 3:
0938:                    addOpcode(Opcode.opc_iload_3);
0939:                    break;
0940:                default:
0941:                    if (index < 256) {
0942:                        addOpcode(Opcode.opc_iload);
0943:                        addByte(index);
0944:                    } else {
0945:                        addOpcode(Opcode.opc_wide);
0946:                        addByte(Opcode.opc_iload);
0947:                        addShort(index);
0948:                    }
0949:                    break;
0950:                }
0951:
0952:                stackHeight++;
0953:            }
0954:
0955:            public void visit_lload(final Instruction inst) {
0956:                final int index = ((LocalVariable) inst.operand()).index();
0957:
0958:                if (index + 2 > maxLocals) {
0959:                    maxLocals = index + 2;
0960:                }
0961:
0962:                if (inst.useSlow()) {
0963:                    if (index < 256) {
0964:                        addOpcode(Opcode.opc_lload);
0965:                        addByte(index);
0966:                    } else {
0967:                        addOpcode(Opcode.opc_wide);
0968:                        addByte(Opcode.opc_lload);
0969:                        addShort(index);
0970:                    }
0971:                    stackHeight++;
0972:                    return;
0973:                }
0974:
0975:                switch (index) {
0976:                case 0:
0977:                    addOpcode(Opcode.opc_lload_0);
0978:                    break;
0979:                case 1:
0980:                    addOpcode(Opcode.opc_lload_1);
0981:                    break;
0982:                case 2:
0983:                    addOpcode(Opcode.opc_lload_2);
0984:                    break;
0985:                case 3:
0986:                    addOpcode(Opcode.opc_lload_3);
0987:                    break;
0988:                default:
0989:                    if (index < 256) {
0990:                        addOpcode(Opcode.opc_lload);
0991:                        addByte(index);
0992:                    } else {
0993:                        addOpcode(Opcode.opc_wide);
0994:                        addByte(Opcode.opc_lload);
0995:                        addShort(index);
0996:                    }
0997:                    break;
0998:                }
0999:
1000:                stackHeight += 2;
1001:            }
1002:
1003:            public void visit_fload(final Instruction inst) {
1004:                final int index = ((LocalVariable) inst.operand()).index();
1005:
1006:                if (index + 1 > maxLocals) {
1007:                    maxLocals = index + 1;
1008:                }
1009:
1010:                if (inst.useSlow()) {
1011:                    if (index < 256) {
1012:                        addOpcode(Opcode.opc_fload);
1013:                        addByte(index);
1014:                    } else {
1015:                        addOpcode(Opcode.opc_wide);
1016:                        addByte(Opcode.opc_fload);
1017:                        addShort(index);
1018:                    }
1019:
1020:                    stackHeight++;
1021:                    return;
1022:                }
1023:
1024:                switch (index) {
1025:                case 0:
1026:                    addOpcode(Opcode.opc_fload_0);
1027:                    break;
1028:                case 1:
1029:                    addOpcode(Opcode.opc_fload_1);
1030:                    break;
1031:                case 2:
1032:                    addOpcode(Opcode.opc_fload_2);
1033:                    break;
1034:                case 3:
1035:                    addOpcode(Opcode.opc_fload_3);
1036:                    break;
1037:                default:
1038:                    if (index < 256) {
1039:                        addOpcode(Opcode.opc_fload);
1040:                        addByte(index);
1041:                    } else {
1042:                        addOpcode(Opcode.opc_wide);
1043:                        addByte(Opcode.opc_fload);
1044:                        addShort(index);
1045:                    }
1046:                    break;
1047:                }
1048:
1049:                stackHeight++;
1050:            }
1051:
1052:            public void visit_dload(final Instruction inst) {
1053:                final int index = ((LocalVariable) inst.operand()).index();
1054:
1055:                if (index + 2 > maxLocals) {
1056:                    maxLocals = index + 2;
1057:                }
1058:
1059:                if (inst.useSlow()) {
1060:                    if (index < 256) {
1061:                        addOpcode(Opcode.opc_dload);
1062:                        addByte(index);
1063:                    } else {
1064:                        addOpcode(Opcode.opc_wide);
1065:                        addByte(Opcode.opc_dload);
1066:                        addShort(index);
1067:                    }
1068:                    stackHeight += 2;
1069:                    return;
1070:                }
1071:
1072:                switch (index) {
1073:                case 0:
1074:                    addOpcode(Opcode.opc_dload_0);
1075:                    break;
1076:                case 1:
1077:                    addOpcode(Opcode.opc_dload_1);
1078:                    break;
1079:                case 2:
1080:                    addOpcode(Opcode.opc_dload_2);
1081:                    break;
1082:                case 3:
1083:                    addOpcode(Opcode.opc_dload_3);
1084:                    break;
1085:                default:
1086:                    if (index < 256) {
1087:                        addOpcode(Opcode.opc_dload);
1088:                        addByte(index);
1089:                    } else {
1090:                        addOpcode(Opcode.opc_wide);
1091:                        addByte(Opcode.opc_dload);
1092:                        addShort(index);
1093:                    }
1094:                    break;
1095:                }
1096:
1097:                stackHeight += 2;
1098:            }
1099:
1100:            public void visit_aload(final Instruction inst) {
1101:                final int index = ((LocalVariable) inst.operand()).index();
1102:
1103:                if (index + 1 > maxLocals) {
1104:                    maxLocals = index + 1;
1105:                }
1106:
1107:                if (inst.useSlow()) {
1108:                    if (index < 256) {
1109:                        addOpcode(Opcode.opc_aload);
1110:                        addByte(index);
1111:                    } else {
1112:                        addOpcode(Opcode.opc_wide);
1113:                        addByte(Opcode.opc_aload);
1114:                        addShort(index);
1115:                    }
1116:                    stackHeight++;
1117:                    return;
1118:                }
1119:
1120:                switch (index) {
1121:                case 0:
1122:                    addOpcode(Opcode.opc_aload_0);
1123:                    break;
1124:                case 1:
1125:                    addOpcode(Opcode.opc_aload_1);
1126:                    break;
1127:                case 2:
1128:                    addOpcode(Opcode.opc_aload_2);
1129:                    break;
1130:                case 3:
1131:                    addOpcode(Opcode.opc_aload_3);
1132:                    break;
1133:                default:
1134:                    if (index < 256) {
1135:                        addOpcode(Opcode.opc_aload);
1136:                        addByte(index);
1137:                    } else {
1138:                        addOpcode(Opcode.opc_wide);
1139:                        addByte(Opcode.opc_aload);
1140:                        addShort(index);
1141:                    }
1142:                    break;
1143:                }
1144:
1145:                stackHeight++;
1146:            }
1147:
1148:            /**
1149:             * Pops an item off the stack.
1150:             */
1151:            public void visit_iaload(final Instruction inst) {
1152:                addOpcode(Opcode.opc_iaload);
1153:                stackHeight--;
1154:            }
1155:
1156:            public void visit_laload(final Instruction inst) {
1157:                addOpcode(Opcode.opc_laload);
1158:                stackHeight += 0;
1159:            }
1160:
1161:            public void visit_faload(final Instruction inst) {
1162:                addOpcode(Opcode.opc_faload);
1163:                stackHeight--;
1164:            }
1165:
1166:            public void visit_daload(final Instruction inst) {
1167:                addOpcode(Opcode.opc_daload);
1168:                stackHeight += 0;
1169:            }
1170:
1171:            public void visit_aaload(final Instruction inst) {
1172:                addOpcode(Opcode.opc_aaload);
1173:                stackHeight--;
1174:            }
1175:
1176:            public void visit_baload(final Instruction inst) {
1177:                addOpcode(Opcode.opc_baload);
1178:                stackHeight--;
1179:            }
1180:
1181:            public void visit_caload(final Instruction inst) {
1182:                addOpcode(Opcode.opc_caload);
1183:                stackHeight--;
1184:            }
1185:
1186:            public void visit_saload(final Instruction inst) {
1187:                addOpcode(Opcode.opc_saload);
1188:                stackHeight--;
1189:            }
1190:
1191:            /*
1192:             * Try to take advantage of smaller opcodes (e.g. istore_1).
1193:             */
1194:            public void visit_istore(final Instruction inst) {
1195:                final int index = ((LocalVariable) inst.operand()).index();
1196:
1197:                if (index + 1 > maxLocals) {
1198:                    maxLocals = index + 1;
1199:                }
1200:
1201:                if (inst.useSlow()) {
1202:                    if (index < 256) {
1203:                        addOpcode(Opcode.opc_istore);
1204:                        addByte(index);
1205:                    } else {
1206:                        addOpcode(Opcode.opc_wide);
1207:                        addByte(Opcode.opc_istore);
1208:                        addShort(index);
1209:                    }
1210:                    stackHeight--;
1211:                    return;
1212:                }
1213:
1214:                switch (index) {
1215:                case 0:
1216:                    addOpcode(Opcode.opc_istore_0);
1217:                    break;
1218:                case 1:
1219:                    addOpcode(Opcode.opc_istore_1);
1220:                    break;
1221:                case 2:
1222:                    addOpcode(Opcode.opc_istore_2);
1223:                    break;
1224:                case 3:
1225:                    addOpcode(Opcode.opc_istore_3);
1226:                    break;
1227:                default:
1228:                    if (index < 256) {
1229:                        addOpcode(Opcode.opc_istore);
1230:                        addByte(index);
1231:                    } else {
1232:                        addOpcode(Opcode.opc_wide);
1233:                        addByte(Opcode.opc_istore);
1234:                        addShort(index);
1235:                    }
1236:                    break;
1237:                }
1238:
1239:                stackHeight--;
1240:            }
1241:
1242:            public void visit_lstore(final Instruction inst) {
1243:                final int index = ((LocalVariable) inst.operand()).index();
1244:
1245:                if (index + 2 > maxLocals) {
1246:                    maxLocals = index + 2;
1247:                }
1248:
1249:                if (inst.useSlow()) {
1250:                    if (index < 256) {
1251:                        addOpcode(Opcode.opc_lstore);
1252:                        addByte(index);
1253:                    } else {
1254:                        addOpcode(Opcode.opc_wide);
1255:                        addByte(Opcode.opc_lstore);
1256:                        addShort(index);
1257:                    }
1258:                    stackHeight -= 2;
1259:                    return;
1260:                }
1261:
1262:                switch (index) {
1263:                case 0:
1264:                    addOpcode(Opcode.opc_lstore_0);
1265:                    break;
1266:                case 1:
1267:                    addOpcode(Opcode.opc_lstore_1);
1268:                    break;
1269:                case 2:
1270:                    addOpcode(Opcode.opc_lstore_2);
1271:                    break;
1272:                case 3:
1273:                    addOpcode(Opcode.opc_lstore_3);
1274:                    break;
1275:                default:
1276:                    if (index < 256) {
1277:                        addOpcode(Opcode.opc_lstore);
1278:                        addByte(index);
1279:                    } else {
1280:                        addOpcode(Opcode.opc_wide);
1281:                        addByte(Opcode.opc_lstore);
1282:                        addShort(index);
1283:                    }
1284:                    break;
1285:                }
1286:
1287:                stackHeight -= 2;
1288:            }
1289:
1290:            public void visit_fstore(final Instruction inst) {
1291:                final int index = ((LocalVariable) inst.operand()).index();
1292:
1293:                if (index + 1 > maxLocals) {
1294:                    maxLocals = index + 1;
1295:                }
1296:
1297:                if (inst.useSlow()) {
1298:                    if (index < 256) {
1299:                        addOpcode(Opcode.opc_fstore);
1300:                        addByte(index);
1301:                    } else {
1302:                        addOpcode(Opcode.opc_wide);
1303:                        addByte(Opcode.opc_fstore);
1304:                        addShort(index);
1305:                    }
1306:                    stackHeight--;
1307:                    return;
1308:                }
1309:
1310:                switch (index) {
1311:                case 0:
1312:                    addOpcode(Opcode.opc_fstore_0);
1313:                    break;
1314:                case 1:
1315:                    addOpcode(Opcode.opc_fstore_1);
1316:                    break;
1317:                case 2:
1318:                    addOpcode(Opcode.opc_fstore_2);
1319:                    break;
1320:                case 3:
1321:                    addOpcode(Opcode.opc_fstore_3);
1322:                    break;
1323:                default:
1324:                    if (index < 256) {
1325:                        addOpcode(Opcode.opc_fstore);
1326:                        addByte(index);
1327:                    } else {
1328:                        addOpcode(Opcode.opc_wide);
1329:                        addByte(Opcode.opc_fstore);
1330:                        addShort(index);
1331:                    }
1332:                    break;
1333:                }
1334:
1335:                stackHeight--;
1336:            }
1337:
1338:            public void visit_dstore(final Instruction inst) {
1339:                final int index = ((LocalVariable) inst.operand()).index();
1340:
1341:                if (index + 2 > maxLocals) {
1342:                    maxLocals = index + 2;
1343:                }
1344:
1345:                if (inst.useSlow()) {
1346:                    if (index < 256) {
1347:                        addOpcode(Opcode.opc_dstore);
1348:                        addByte(index);
1349:                    } else {
1350:                        addOpcode(Opcode.opc_wide);
1351:                        addByte(Opcode.opc_dstore);
1352:                        addShort(index);
1353:                    }
1354:                    stackHeight -= 2;
1355:                    return;
1356:                }
1357:
1358:                switch (index) {
1359:                case 0:
1360:                    addOpcode(Opcode.opc_dstore_0);
1361:                    break;
1362:                case 1:
1363:                    addOpcode(Opcode.opc_dstore_1);
1364:                    break;
1365:                case 2:
1366:                    addOpcode(Opcode.opc_dstore_2);
1367:                    break;
1368:                case 3:
1369:                    addOpcode(Opcode.opc_dstore_3);
1370:                    break;
1371:                default:
1372:                    if (index < 256) {
1373:                        addOpcode(Opcode.opc_dstore);
1374:                        addByte(index);
1375:                    } else {
1376:                        addOpcode(Opcode.opc_wide);
1377:                        addByte(Opcode.opc_dstore);
1378:                        addShort(index);
1379:                    }
1380:                    break;
1381:                }
1382:
1383:                stackHeight -= 2;
1384:            }
1385:
1386:            public void visit_astore(final Instruction inst) {
1387:                final int index = ((LocalVariable) inst.operand()).index();
1388:
1389:                if (index + 1 > maxLocals) {
1390:                    maxLocals = index + 1;
1391:                }
1392:
1393:                if (inst.useSlow()) {
1394:                    if (index < 256) {
1395:                        addOpcode(Opcode.opc_astore);
1396:                        addByte(index);
1397:                    } else {
1398:                        addOpcode(Opcode.opc_wide);
1399:                        addByte(Opcode.opc_astore);
1400:                        addShort(index);
1401:                    }
1402:                    stackHeight--;
1403:                    return;
1404:                }
1405:
1406:                switch (index) {
1407:                case 0:
1408:                    addOpcode(Opcode.opc_astore_0);
1409:                    break;
1410:                case 1:
1411:                    addOpcode(Opcode.opc_astore_1);
1412:                    break;
1413:                case 2:
1414:                    addOpcode(Opcode.opc_astore_2);
1415:                    break;
1416:                case 3:
1417:                    addOpcode(Opcode.opc_astore_3);
1418:                    break;
1419:                default:
1420:                    if (index < 256) {
1421:                        addOpcode(Opcode.opc_astore);
1422:                        addByte(index);
1423:                    } else {
1424:                        addOpcode(Opcode.opc_wide);
1425:                        addByte(Opcode.opc_astore);
1426:                        addShort(index);
1427:                    }
1428:                    break;
1429:                }
1430:
1431:                stackHeight--;
1432:            }
1433:
1434:            /*
1435:             * Store into an array. Pop 3+ items off the stack.
1436:             */
1437:            public void visit_iastore(final Instruction inst) {
1438:                addOpcode(Opcode.opc_iastore);
1439:                stackHeight -= 3;
1440:            }
1441:
1442:            public void visit_lastore(final Instruction inst) {
1443:                addOpcode(Opcode.opc_lastore);
1444:                stackHeight -= 4;
1445:            }
1446:
1447:            public void visit_fastore(final Instruction inst) {
1448:                addOpcode(Opcode.opc_fastore);
1449:                stackHeight -= 3;
1450:            }
1451:
1452:            public void visit_dastore(final Instruction inst) {
1453:                addOpcode(Opcode.opc_dastore);
1454:                stackHeight -= 4;
1455:            }
1456:
1457:            public void visit_aastore(final Instruction inst) {
1458:                addOpcode(Opcode.opc_aastore);
1459:                stackHeight -= 3;
1460:            }
1461:
1462:            public void visit_bastore(final Instruction inst) {
1463:                addOpcode(Opcode.opc_bastore);
1464:                stackHeight -= 3;
1465:            }
1466:
1467:            public void visit_castore(final Instruction inst) {
1468:                addOpcode(Opcode.opc_castore);
1469:                stackHeight -= 3;
1470:            }
1471:
1472:            public void visit_sastore(final Instruction inst) {
1473:                addOpcode(Opcode.opc_sastore);
1474:                stackHeight -= 3;
1475:            }
1476:
1477:            public void visit_pop(final Instruction inst) {
1478:                addOpcode(Opcode.opc_pop);
1479:                stackHeight--;
1480:            }
1481:
1482:            public void visit_pop2(final Instruction inst) {
1483:                addOpcode(Opcode.opc_pop2);
1484:                stackHeight -= 2;
1485:            }
1486:
1487:            public void visit_dup(final Instruction inst) {
1488:                addOpcode(Opcode.opc_dup);
1489:                stackHeight++;
1490:            }
1491:
1492:            public void visit_dup_x1(final Instruction inst) {
1493:                addOpcode(Opcode.opc_dup_x1);
1494:                stackHeight++;
1495:            }
1496:
1497:            public void visit_dup_x2(final Instruction inst) {
1498:                addOpcode(Opcode.opc_dup_x2);
1499:                stackHeight++;
1500:            }
1501:
1502:            public void visit_dup2(final Instruction inst) {
1503:                addOpcode(Opcode.opc_dup2);
1504:                stackHeight += 2;
1505:            }
1506:
1507:            public void visit_dup2_x1(final Instruction inst) {
1508:                addOpcode(Opcode.opc_dup2_x1);
1509:                stackHeight += 2;
1510:            }
1511:
1512:            public void visit_dup2_x2(final Instruction inst) {
1513:                addOpcode(Opcode.opc_dup2_x2);
1514:                stackHeight += 2;
1515:            }
1516:
1517:            public void visit_swap(final Instruction inst) {
1518:                addOpcode(Opcode.opc_swap);
1519:            }
1520:
1521:            public void visit_iadd(final Instruction inst) {
1522:                addOpcode(Opcode.opc_iadd);
1523:                stackHeight--;
1524:            }
1525:
1526:            public void visit_ladd(final Instruction inst) {
1527:                addOpcode(Opcode.opc_ladd);
1528:                stackHeight -= 2;
1529:            }
1530:
1531:            public void visit_fadd(final Instruction inst) {
1532:                addOpcode(Opcode.opc_fadd);
1533:                stackHeight--;
1534:            }
1535:
1536:            public void visit_dadd(final Instruction inst) {
1537:                addOpcode(Opcode.opc_dadd);
1538:                stackHeight -= 2;
1539:            }
1540:
1541:            public void visit_isub(final Instruction inst) {
1542:                addOpcode(Opcode.opc_isub);
1543:                stackHeight--;
1544:            }
1545:
1546:            public void visit_lsub(final Instruction inst) {
1547:                addOpcode(Opcode.opc_lsub);
1548:                stackHeight -= 2;
1549:            }
1550:
1551:            public void visit_fsub(final Instruction inst) {
1552:                addOpcode(Opcode.opc_fsub);
1553:                stackHeight--;
1554:            }
1555:
1556:            public void visit_dsub(final Instruction inst) {
1557:                addOpcode(Opcode.opc_dsub);
1558:                stackHeight -= 2;
1559:            }
1560:
1561:            public void visit_imul(final Instruction inst) {
1562:                addOpcode(Opcode.opc_imul);
1563:                stackHeight--;
1564:            }
1565:
1566:            public void visit_lmul(final Instruction inst) {
1567:                addOpcode(Opcode.opc_lmul);
1568:                stackHeight -= 2;
1569:            }
1570:
1571:            public void visit_fmul(final Instruction inst) {
1572:                addOpcode(Opcode.opc_fmul);
1573:                stackHeight--;
1574:            }
1575:
1576:            public void visit_dmul(final Instruction inst) {
1577:                addOpcode(Opcode.opc_dmul);
1578:                stackHeight -= 2;
1579:            }
1580:
1581:            public void visit_idiv(final Instruction inst) {
1582:                addOpcode(Opcode.opc_idiv);
1583:                stackHeight--;
1584:            }
1585:
1586:            public void visit_ldiv(final Instruction inst) {
1587:                addOpcode(Opcode.opc_ldiv);
1588:                stackHeight -= 2;
1589:            }
1590:
1591:            public void visit_fdiv(final Instruction inst) {
1592:                addOpcode(Opcode.opc_fdiv);
1593:                stackHeight--;
1594:            }
1595:
1596:            public void visit_ddiv(final Instruction inst) {
1597:                addOpcode(Opcode.opc_ddiv);
1598:                stackHeight -= 2;
1599:            }
1600:
1601:            public void visit_irem(final Instruction inst) {
1602:                addOpcode(Opcode.opc_irem);
1603:                stackHeight--;
1604:            }
1605:
1606:            public void visit_lrem(final Instruction inst) {
1607:                addOpcode(Opcode.opc_lrem);
1608:                stackHeight -= 2;
1609:            }
1610:
1611:            public void visit_frem(final Instruction inst) {
1612:                addOpcode(Opcode.opc_frem);
1613:                stackHeight--;
1614:            }
1615:
1616:            public void visit_drem(final Instruction inst) {
1617:                addOpcode(Opcode.opc_drem);
1618:                stackHeight -= 2;
1619:            }
1620:
1621:            public void visit_ineg(final Instruction inst) {
1622:                addOpcode(Opcode.opc_ineg);
1623:                stackHeight += 0;
1624:            }
1625:
1626:            public void visit_lneg(final Instruction inst) {
1627:                addOpcode(Opcode.opc_lneg);
1628:                stackHeight += 0;
1629:            }
1630:
1631:            public void visit_fneg(final Instruction inst) {
1632:                addOpcode(Opcode.opc_fneg);
1633:                stackHeight += 0;
1634:            }
1635:
1636:            public void visit_dneg(final Instruction inst) {
1637:                addOpcode(Opcode.opc_dneg);
1638:                stackHeight += 0;
1639:            }
1640:
1641:            public void visit_ishl(final Instruction inst) {
1642:                addOpcode(Opcode.opc_ishl);
1643:                stackHeight--;
1644:            }
1645:
1646:            public void visit_lshl(final Instruction inst) {
1647:                addOpcode(Opcode.opc_lshl);
1648:                stackHeight--;
1649:            }
1650:
1651:            public void visit_ishr(final Instruction inst) {
1652:                addOpcode(Opcode.opc_ishr);
1653:                stackHeight--;
1654:            }
1655:
1656:            public void visit_lshr(final Instruction inst) {
1657:                addOpcode(Opcode.opc_lshr);
1658:                stackHeight--;
1659:            }
1660:
1661:            public void visit_iushr(final Instruction inst) {
1662:                addOpcode(Opcode.opc_iushr);
1663:                stackHeight--;
1664:            }
1665:
1666:            public void visit_lushr(final Instruction inst) {
1667:                addOpcode(Opcode.opc_lushr);
1668:                stackHeight--;
1669:            }
1670:
1671:            public void visit_iand(final Instruction inst) {
1672:                addOpcode(Opcode.opc_iand);
1673:                stackHeight--;
1674:            }
1675:
1676:            public void visit_land(final Instruction inst) {
1677:                addOpcode(Opcode.opc_land);
1678:                stackHeight -= 2;
1679:            }
1680:
1681:            public void visit_ior(final Instruction inst) {
1682:                addOpcode(Opcode.opc_ior);
1683:                stackHeight--;
1684:            }
1685:
1686:            public void visit_lor(final Instruction inst) {
1687:                addOpcode(Opcode.opc_lor);
1688:                stackHeight -= 2;
1689:            }
1690:
1691:            public void visit_ixor(final Instruction inst) {
1692:                addOpcode(Opcode.opc_ixor);
1693:                stackHeight--;
1694:            }
1695:
1696:            public void visit_lxor(final Instruction inst) {
1697:                addOpcode(Opcode.opc_lxor);
1698:                stackHeight -= 2;
1699:            }
1700:
1701:            public void visit_iinc(final Instruction inst) {
1702:                final IncOperand operand = (IncOperand) inst.operand();
1703:
1704:                final int index = operand.var().index();
1705:
1706:                if (index + 1 > maxLocals) {
1707:                    maxLocals = index + 1;
1708:                }
1709:
1710:                final int incr = operand.incr();
1711:
1712:                if ((index < 256) && ((byte) incr == incr)) {
1713:                    addOpcode(Opcode.opc_iinc);
1714:                    addByte(index);
1715:                    addByte(incr);
1716:                } else {
1717:                    addOpcode(Opcode.opc_wide);
1718:                    addByte(Opcode.opc_iinc);
1719:                    addShort(index);
1720:                    addShort(incr);
1721:                }
1722:
1723:                stackHeight += 0;
1724:            }
1725:
1726:            public void visit_i2l(final Instruction inst) {
1727:                addOpcode(Opcode.opc_i2l);
1728:                stackHeight++;
1729:            }
1730:
1731:            public void visit_i2f(final Instruction inst) {
1732:                addOpcode(Opcode.opc_i2f);
1733:                stackHeight += 0;
1734:            }
1735:
1736:            public void visit_i2d(final Instruction inst) {
1737:                addOpcode(Opcode.opc_i2d);
1738:                stackHeight++;
1739:            }
1740:
1741:            public void visit_l2i(final Instruction inst) {
1742:                addOpcode(Opcode.opc_l2i);
1743:                stackHeight--;
1744:            }
1745:
1746:            public void visit_l2f(final Instruction inst) {
1747:                addOpcode(Opcode.opc_l2f);
1748:                stackHeight--;
1749:            }
1750:
1751:            public void visit_l2d(final Instruction inst) {
1752:                addOpcode(Opcode.opc_l2d);
1753:                stackHeight += 0;
1754:            }
1755:
1756:            public void visit_f2i(final Instruction inst) {
1757:                addOpcode(Opcode.opc_f2i);
1758:                stackHeight += 0;
1759:            }
1760:
1761:            public void visit_f2l(final Instruction inst) {
1762:                addOpcode(Opcode.opc_f2l);
1763:                stackHeight++;
1764:            }
1765:
1766:            public void visit_f2d(final Instruction inst) {
1767:                addOpcode(Opcode.opc_f2d);
1768:                stackHeight++;
1769:            }
1770:
1771:            public void visit_d2i(final Instruction inst) {
1772:                addOpcode(Opcode.opc_d2i);
1773:                stackHeight--;
1774:            }
1775:
1776:            public void visit_d2l(final Instruction inst) {
1777:                addOpcode(Opcode.opc_d2l);
1778:                stackHeight += 0;
1779:            }
1780:
1781:            public void visit_d2f(final Instruction inst) {
1782:                addOpcode(Opcode.opc_d2f);
1783:                stackHeight--;
1784:            }
1785:
1786:            public void visit_i2b(final Instruction inst) {
1787:                addOpcode(Opcode.opc_i2b);
1788:                stackHeight += 0;
1789:            }
1790:
1791:            public void visit_i2c(final Instruction inst) {
1792:                addOpcode(Opcode.opc_i2c);
1793:                stackHeight += 0;
1794:            }
1795:
1796:            public void visit_i2s(final Instruction inst) {
1797:                addOpcode(Opcode.opc_i2s);
1798:                stackHeight += 0;
1799:            }
1800:
1801:            public void visit_lcmp(final Instruction inst) {
1802:                addOpcode(Opcode.opc_lcmp);
1803:                stackHeight -= 3;
1804:            }
1805:
1806:            public void visit_fcmpl(final Instruction inst) {
1807:                addOpcode(Opcode.opc_fcmpl);
1808:                stackHeight--;
1809:            }
1810:
1811:            public void visit_fcmpg(final Instruction inst) {
1812:                addOpcode(Opcode.opc_fcmpg);
1813:                stackHeight--;
1814:            }
1815:
1816:            public void visit_dcmpl(final Instruction inst) {
1817:                addOpcode(Opcode.opc_dcmpl);
1818:                stackHeight -= 3;
1819:            }
1820:
1821:            public void visit_dcmpg(final Instruction inst) {
1822:                addOpcode(Opcode.opc_dcmpg);
1823:                stackHeight -= 3;
1824:            }
1825:
1826:            /*
1827:             * Handle long branches.
1828:             */
1829:            public void visit_ifeq(final Instruction inst) {
1830:                if (longBranch) {
1831:                    final Label tmp = method.newLabel();
1832:                    addOpcode(Opcode.opc_ifne);
1833:                    addBranch(tmp);
1834:                    addOpcode(Opcode.opc_goto_w);
1835:                    addLongBranch((Label) inst.operand());
1836:                    addLabel(tmp);
1837:                } else {
1838:                    addOpcode(Opcode.opc_ifeq);
1839:                    addBranch((Label) inst.operand());
1840:                }
1841:
1842:                stackHeight--;
1843:            }
1844:
1845:            public void visit_ifne(final Instruction inst) {
1846:                if (longBranch) {
1847:                    final Label tmp = method.newLabel();
1848:                    addOpcode(Opcode.opc_ifeq);
1849:                    addBranch(tmp);
1850:                    addOpcode(Opcode.opc_goto_w);
1851:                    addLongBranch((Label) inst.operand());
1852:                    addLabel(tmp);
1853:                } else {
1854:                    addOpcode(Opcode.opc_ifne);
1855:                    addBranch((Label) inst.operand());
1856:                }
1857:
1858:                stackHeight--;
1859:            }
1860:
1861:            public void visit_iflt(final Instruction inst) {
1862:                if (longBranch) {
1863:                    final Label tmp = method.newLabel();
1864:                    addOpcode(Opcode.opc_ifge);
1865:                    addBranch(tmp);
1866:                    addOpcode(Opcode.opc_goto_w);
1867:                    addLongBranch((Label) inst.operand());
1868:                    addLabel(tmp);
1869:                } else {
1870:                    addOpcode(Opcode.opc_iflt);
1871:                    addBranch((Label) inst.operand());
1872:                }
1873:
1874:                stackHeight--;
1875:            }
1876:
1877:            public void visit_ifge(final Instruction inst) {
1878:                if (longBranch) {
1879:                    final Label tmp = method.newLabel();
1880:                    addOpcode(Opcode.opc_iflt);
1881:                    addBranch(tmp);
1882:                    addOpcode(Opcode.opc_goto_w);
1883:                    addLongBranch((Label) inst.operand());
1884:                    addLabel(tmp);
1885:                } else {
1886:                    addOpcode(Opcode.opc_ifge);
1887:                    addBranch((Label) inst.operand());
1888:                }
1889:
1890:                stackHeight--;
1891:            }
1892:
1893:            public void visit_ifgt(final Instruction inst) {
1894:                if (longBranch) {
1895:                    final Label tmp = method.newLabel();
1896:                    addOpcode(Opcode.opc_ifle);
1897:                    addBranch(tmp);
1898:                    addOpcode(Opcode.opc_goto_w);
1899:                    addLongBranch((Label) inst.operand());
1900:                    addLabel(tmp);
1901:                } else {
1902:                    addOpcode(Opcode.opc_ifgt);
1903:                    addBranch((Label) inst.operand());
1904:                }
1905:
1906:                stackHeight--;
1907:            }
1908:
1909:            public void visit_ifle(final Instruction inst) {
1910:                if (longBranch) {
1911:                    final Label tmp = method.newLabel();
1912:                    addOpcode(Opcode.opc_ifgt);
1913:                    addBranch(tmp);
1914:                    addOpcode(Opcode.opc_goto_w);
1915:                    addLongBranch((Label) inst.operand());
1916:                    addLabel(tmp);
1917:                } else {
1918:                    addOpcode(Opcode.opc_ifle);
1919:                    addBranch((Label) inst.operand());
1920:                }
1921:
1922:                stackHeight--;
1923:            }
1924:
1925:            public void visit_if_icmpeq(final Instruction inst) {
1926:                if (longBranch) {
1927:                    final Label tmp = method.newLabel();
1928:                    addOpcode(Opcode.opc_if_icmpne);
1929:                    addBranch(tmp);
1930:                    addOpcode(Opcode.opc_goto_w);
1931:                    addLongBranch((Label) inst.operand());
1932:                    addLabel(tmp);
1933:                } else {
1934:                    addOpcode(Opcode.opc_if_icmpeq);
1935:                    addBranch((Label) inst.operand());
1936:                }
1937:
1938:                stackHeight -= 2;
1939:            }
1940:
1941:            public void visit_if_icmpne(final Instruction inst) {
1942:                if (longBranch) {
1943:                    final Label tmp = method.newLabel();
1944:                    addOpcode(Opcode.opc_if_icmpeq);
1945:                    addBranch(tmp);
1946:                    addOpcode(Opcode.opc_goto_w);
1947:                    addLongBranch((Label) inst.operand());
1948:                    addLabel(tmp);
1949:                } else {
1950:                    addOpcode(Opcode.opc_if_icmpne);
1951:                    addBranch((Label) inst.operand());
1952:                }
1953:
1954:                stackHeight -= 2;
1955:            }
1956:
1957:            public void visit_if_icmplt(final Instruction inst) {
1958:                if (longBranch) {
1959:                    final Label tmp = method.newLabel();
1960:                    addOpcode(Opcode.opc_if_icmpge);
1961:                    addBranch(tmp);
1962:                    addOpcode(Opcode.opc_goto_w);
1963:                    addLongBranch((Label) inst.operand());
1964:                    addLabel(tmp);
1965:                } else {
1966:                    addOpcode(Opcode.opc_if_icmplt);
1967:                    addBranch((Label) inst.operand());
1968:                }
1969:
1970:                stackHeight -= 2;
1971:            }
1972:
1973:            public void visit_if_icmpge(final Instruction inst) {
1974:                if (longBranch) {
1975:                    final Label tmp = method.newLabel();
1976:                    addOpcode(Opcode.opc_if_icmplt);
1977:                    addBranch(tmp);
1978:                    addOpcode(Opcode.opc_goto_w);
1979:                    addLongBranch((Label) inst.operand());
1980:                    addLabel(tmp);
1981:                } else {
1982:                    addOpcode(Opcode.opc_if_icmpge);
1983:                    addBranch((Label) inst.operand());
1984:                }
1985:
1986:                stackHeight -= 2;
1987:            }
1988:
1989:            public void visit_if_icmpgt(final Instruction inst) {
1990:                if (longBranch) {
1991:                    final Label tmp = method.newLabel();
1992:                    addOpcode(Opcode.opc_if_icmple);
1993:                    addBranch(tmp);
1994:                    addOpcode(Opcode.opc_goto_w);
1995:                    addLongBranch((Label) inst.operand());
1996:                    addLabel(tmp);
1997:                } else {
1998:                    addOpcode(Opcode.opc_if_icmpgt);
1999:                    addBranch((Label) inst.operand());
2000:                }
2001:
2002:                stackHeight -= 2;
2003:            }
2004:
2005:            public void visit_if_icmple(final Instruction inst) {
2006:                if (longBranch) {
2007:                    final Label tmp = method.newLabel();
2008:                    addOpcode(Opcode.opc_if_icmpgt);
2009:                    addBranch(tmp);
2010:                    addOpcode(Opcode.opc_goto_w);
2011:                    addLongBranch((Label) inst.operand());
2012:                    addLabel(tmp);
2013:                } else {
2014:                    addOpcode(Opcode.opc_if_icmple);
2015:                    addBranch((Label) inst.operand());
2016:                }
2017:
2018:                stackHeight -= 2;
2019:            }
2020:
2021:            public void visit_if_acmpeq(final Instruction inst) {
2022:                if (longBranch) {
2023:                    final Label tmp = method.newLabel();
2024:                    addOpcode(Opcode.opc_if_acmpne);
2025:                    addBranch(tmp);
2026:                    addOpcode(Opcode.opc_goto_w);
2027:                    addLongBranch((Label) inst.operand());
2028:                    addLabel(tmp);
2029:                } else {
2030:                    addOpcode(Opcode.opc_if_acmpeq);
2031:                    addBranch((Label) inst.operand());
2032:                }
2033:
2034:                stackHeight -= 2;
2035:            }
2036:
2037:            public void visit_if_acmpne(final Instruction inst) {
2038:                if (longBranch) {
2039:                    final Label tmp = method.newLabel();
2040:                    addOpcode(Opcode.opc_if_acmpeq);
2041:                    addBranch(tmp);
2042:                    addOpcode(Opcode.opc_goto_w);
2043:                    addLongBranch((Label) inst.operand());
2044:                    addLabel(tmp);
2045:                } else {
2046:                    addOpcode(Opcode.opc_if_acmpne);
2047:                    addBranch((Label) inst.operand());
2048:                }
2049:
2050:                stackHeight -= 2;
2051:            }
2052:
2053:            public void visit_goto(final Instruction inst) {
2054:                if (longBranch) {
2055:                    addOpcode(Opcode.opc_goto_w);
2056:                    addLongBranch((Label) inst.operand());
2057:                } else {
2058:                    addOpcode(Opcode.opc_goto);
2059:                    addBranch((Label) inst.operand());
2060:                }
2061:
2062:                stackHeight += 0;
2063:            }
2064:
2065:            public void visit_jsr(final Instruction inst) {
2066:                if (longBranch) {
2067:                    addOpcode(Opcode.opc_jsr_w);
2068:                    addLongBranch((Label) inst.operand());
2069:                } else {
2070:                    addOpcode(Opcode.opc_jsr);
2071:                    addBranch((Label) inst.operand());
2072:                }
2073:
2074:                stackHeight++;
2075:            }
2076:
2077:            public void visit_ret(final Instruction inst) {
2078:                final int index = ((LocalVariable) inst.operand()).index();
2079:
2080:                if (index + 1 > maxLocals) {
2081:                    maxLocals = index + 1;
2082:                }
2083:
2084:                if (index < 256) {
2085:                    addOpcode(Opcode.opc_ret);
2086:                    addByte(index);
2087:                } else {
2088:                    addOpcode(Opcode.opc_wide);
2089:                    addByte(Opcode.opc_ret);
2090:                    addShort(index);
2091:                }
2092:
2093:                stackHeight += 0;
2094:            }
2095:
2096:            public void visit_switch(final Instruction inst) {
2097:                final Switch sw = (Switch) inst.operand();
2098:
2099:                final int[] values = sw.values();
2100:                final Label[] targets = sw.targets();
2101:
2102:                if (values.length == 0) {
2103:                    if (longBranch) {
2104:                        addOpcode(Opcode.opc_pop); // Pop switch "index" off stack
2105:                        addOpcode(Opcode.opc_goto_w);
2106:                        addLongBranch(sw.defaultTarget());
2107:                    } else {
2108:                        addOpcode(Opcode.opc_pop); // Pop switch "index" off stack
2109:                        addOpcode(Opcode.opc_goto);
2110:                        addBranch(sw.defaultTarget());
2111:                    }
2112:                } else if (sw.hasContiguousValues()) {
2113:                    addOpcode(Opcode.opc_tableswitch);
2114:                    addLongBranch(sw.defaultTarget());
2115:
2116:                    addInt(values[0]);
2117:                    addInt(values[values.length - 1]);
2118:
2119:                    for (int i = 0; i < targets.length; i++) {
2120:                        addLongBranch(targets[i]);
2121:                    }
2122:                } else {
2123:                    addOpcode(Opcode.opc_lookupswitch);
2124:                    addLongBranch(sw.defaultTarget());
2125:
2126:                    addInt(values.length);
2127:
2128:                    for (int i = 0; i < targets.length; i++) {
2129:                        addInt(values[i]);
2130:                        addLongBranch(targets[i]);
2131:                    }
2132:                }
2133:
2134:                stackHeight--;
2135:            }
2136:
2137:            public void visit_ireturn(final Instruction inst) {
2138:                addOpcode(Opcode.opc_ireturn);
2139:                stackHeight = 0;
2140:            }
2141:
2142:            public void visit_lreturn(final Instruction inst) {
2143:                addOpcode(Opcode.opc_lreturn);
2144:                stackHeight = 0;
2145:            }
2146:
2147:            public void visit_freturn(final Instruction inst) {
2148:                addOpcode(Opcode.opc_freturn);
2149:                stackHeight = 0;
2150:            }
2151:
2152:            public void visit_dreturn(final Instruction inst) {
2153:                addOpcode(Opcode.opc_dreturn);
2154:                stackHeight = 0;
2155:            }
2156:
2157:            public void visit_areturn(final Instruction inst) {
2158:                addOpcode(Opcode.opc_areturn);
2159:                stackHeight = 0;
2160:            }
2161:
2162:            public void visit_return(final Instruction inst) {
2163:                addOpcode(Opcode.opc_return);
2164:                stackHeight = 0;
2165:            }
2166:
2167:            public void visit_getstatic(final Instruction inst) {
2168:                final int index = constants.addConstant(Constant.FIELD_REF,
2169:                        inst.operand());
2170:                addOpcode(Opcode.opc_getstatic);
2171:                addShort(index);
2172:
2173:                final Type type = ((MemberRef) inst.operand()).nameAndType()
2174:                        .type();
2175:                stackHeight += type.stackHeight();
2176:            }
2177:
2178:            public void visit_putstatic(final Instruction inst) {
2179:                final int index = constants.addConstant(Constant.FIELD_REF,
2180:                        inst.operand());
2181:                addOpcode(Opcode.opc_putstatic);
2182:                addShort(index);
2183:
2184:                final Type type = ((MemberRef) inst.operand()).nameAndType()
2185:                        .type();
2186:                stackHeight -= type.stackHeight();
2187:            }
2188:
2189:            public void visit_putstatic_nowb(final Instruction inst) {
2190:                final int index = constants.addConstant(Constant.FIELD_REF,
2191:                        inst.operand());
2192:                addOpcode(Opcode.opc_putstatic_nowb);
2193:                addShort(index);
2194:
2195:                final Type type = ((MemberRef) inst.operand()).nameAndType()
2196:                        .type();
2197:                stackHeight -= type.stackHeight();
2198:            }
2199:
2200:            public void visit_getfield(final Instruction inst) {
2201:                final int index = constants.addConstant(Constant.FIELD_REF,
2202:                        inst.operand());
2203:                addOpcode(Opcode.opc_getfield);
2204:                addShort(index);
2205:
2206:                final Type type = ((MemberRef) inst.operand()).nameAndType()
2207:                        .type();
2208:                stackHeight += type.stackHeight() - 1;
2209:            }
2210:
2211:            public void visit_putfield(final Instruction inst) {
2212:                final int index = constants.addConstant(Constant.FIELD_REF,
2213:                        inst.operand());
2214:                addOpcode(Opcode.opc_putfield);
2215:                addShort(index);
2216:
2217:                final Type type = ((MemberRef) inst.operand()).nameAndType()
2218:                        .type();
2219:                stackHeight -= type.stackHeight() + 1;
2220:            }
2221:
2222:            public void visit_putfield_nowb(final Instruction inst) {
2223:                final int index = constants.addConstant(Constant.FIELD_REF,
2224:                        inst.operand());
2225:                addOpcode(Opcode.opc_putfield_nowb);
2226:                addShort(index);
2227:
2228:                final Type type = ((MemberRef) inst.operand()).nameAndType()
2229:                        .type();
2230:                stackHeight -= type.stackHeight() + 1;
2231:            }
2232:
2233:            public void visit_invokevirtual(final Instruction inst) {
2234:                final int index = constants.addConstant(Constant.METHOD_REF,
2235:                        inst.operand());
2236:                addOpcode(Opcode.opc_invokevirtual);
2237:                addShort(index);
2238:
2239:                final MemberRef method = (MemberRef) inst.operand();
2240:                final Type type = method.nameAndType().type();
2241:
2242:                stackHeight += type.returnType().stackHeight()
2243:                        - type.stackHeight() - 1;
2244:            }
2245:
2246:            public void visit_invokespecial(final Instruction inst) {
2247:                final int index = constants.addConstant(Constant.METHOD_REF,
2248:                        inst.operand());
2249:                addOpcode(Opcode.opc_invokespecial);
2250:                addShort(index);
2251:
2252:                final MemberRef method = (MemberRef) inst.operand();
2253:                final Type type = method.nameAndType().type();
2254:
2255:                stackHeight += type.returnType().stackHeight()
2256:                        - type.stackHeight() - 1;
2257:            }
2258:
2259:            public void visit_invokestatic(final Instruction inst) {
2260:                final int index = constants.addConstant(Constant.METHOD_REF,
2261:                        inst.operand());
2262:                addOpcode(Opcode.opc_invokestatic);
2263:                addShort(index);
2264:
2265:                final MemberRef method = (MemberRef) inst.operand();
2266:                final Type type = method.nameAndType().type();
2267:
2268:                Assert.isTrue(type.isMethod(),
2269:                        "Trying to invoke a type that is not a method: "
2270:                                + method);
2271:
2272:                stackHeight += type.returnType().stackHeight()
2273:                        - type.stackHeight();
2274:            }
2275:
2276:            public void visit_invokeinterface(final Instruction inst) {
2277:                final int index = constants.addConstant(
2278:                        Constant.INTERFACE_METHOD_REF, inst.operand());
2279:                final MemberRef method = (MemberRef) constants
2280:                        .constantAt(index);
2281:                final Type type = method.nameAndType().type();
2282:
2283:                addOpcode(Opcode.opc_invokeinterface);
2284:                addShort(index);
2285:                addByte(type.stackHeight() + 1);
2286:                addByte(0);
2287:
2288:                stackHeight += type.returnType().stackHeight()
2289:                        - type.stackHeight() - 1;
2290:            }
2291:
2292:            public void visit_new(final Instruction inst) {
2293:                final int index = constants.addConstant(Constant.CLASS, inst
2294:                        .operand());
2295:                addOpcode(Opcode.opc_new);
2296:                addShort(index);
2297:
2298:                stackHeight++;
2299:            }
2300:
2301:            public void visit_newarray(final Instruction inst) {
2302:                final Type type = (Type) inst.operand();
2303:
2304:                if (type.isReference()) {
2305:                    final int index = constants.addConstant(Constant.CLASS,
2306:                            type);
2307:                    addOpcode(Opcode.opc_anewarray);
2308:                    addShort(index);
2309:                } else {
2310:                    addOpcode(Opcode.opc_newarray);
2311:                    addByte(type.typeCode());
2312:                }
2313:
2314:                stackHeight += 0;
2315:            }
2316:
2317:            public void visit_arraylength(final Instruction inst) {
2318:                addOpcode(Opcode.opc_arraylength);
2319:                stackHeight += 0;
2320:            }
2321:
2322:            public void visit_athrow(final Instruction inst) {
2323:                addOpcode(Opcode.opc_athrow);
2324:                stackHeight = 0;
2325:            }
2326:
2327:            public void visit_checkcast(final Instruction inst) {
2328:                final int index = constants.addConstant(Constant.CLASS, inst
2329:                        .operand());
2330:                addOpcode(Opcode.opc_checkcast);
2331:                addShort(index);
2332:                stackHeight += 0;
2333:            }
2334:
2335:            public void visit_instanceof (final Instruction inst) {
2336:                final int index = constants.addConstant(Constant.CLASS, inst
2337:                        .operand());
2338:                addOpcode(Opcode.opc_instanceof );
2339:                addShort(index);
2340:                stackHeight += 0;
2341:            }
2342:
2343:            public void visit_monitorenter(final Instruction inst) {
2344:                addOpcode(Opcode.opc_monitorenter);
2345:                stackHeight--;
2346:            }
2347:
2348:            public void visit_monitorexit(final Instruction inst) {
2349:                addOpcode(Opcode.opc_monitorexit);
2350:                stackHeight--;
2351:            }
2352:
2353:            public void visit_multianewarray(final Instruction inst) {
2354:                final MultiArrayOperand operand = (MultiArrayOperand) inst
2355:                        .operand();
2356:                final Type type = operand.type();
2357:                final int dim = operand.dimensions();
2358:                final int index = constants.addConstant(Constant.CLASS, type);
2359:                addOpcode(Opcode.opc_multianewarray);
2360:                addShort(index);
2361:                addByte(dim);
2362:
2363:                stackHeight += 1 - dim;
2364:            }
2365:
2366:            public void visit_ifnull(final Instruction inst) {
2367:                if (longBranch) {
2368:                    final Label tmp = method.newLabel();
2369:                    addOpcode(Opcode.opc_ifnonnull);
2370:                    addBranch(tmp);
2371:                    addOpcode(Opcode.opc_goto_w);
2372:                    addLongBranch((Label) inst.operand());
2373:                    addLabel(tmp);
2374:                } else {
2375:                    addOpcode(Opcode.opc_ifnull);
2376:                    addBranch((Label) inst.operand());
2377:                }
2378:
2379:                stackHeight--;
2380:            }
2381:
2382:            public void visit_ifnonnull(final Instruction inst) {
2383:                if (longBranch) {
2384:                    final Label tmp = method.newLabel();
2385:                    addOpcode(Opcode.opc_ifnull);
2386:                    addBranch(tmp);
2387:                    addOpcode(Opcode.opc_goto_w);
2388:                    addLongBranch((Label) inst.operand());
2389:                    addLabel(tmp);
2390:                } else {
2391:                    addOpcode(Opcode.opc_ifnonnull);
2392:                    addBranch((Label) inst.operand());
2393:                }
2394:
2395:                stackHeight--;
2396:            }
2397:
2398:            public void visit_rc(final Instruction inst) {
2399:                final Integer operand = (Integer) inst.operand();
2400:                addOpcode(Opcode.opc_rc);
2401:                addByte(operand.intValue());
2402:                stackHeight += 0;
2403:            }
2404:
2405:            public void visit_aswizzle(final Instruction inst) {
2406:                addOpcode(Opcode.opc_aswizzle);
2407:                stackHeight -= 2;
2408:            }
2409:
2410:            public void visit_aswrange(final Instruction inst) {
2411:                addOpcode(Opcode.opc_aswrange);
2412:                stackHeight -= 3;
2413:            }
2414:
2415:            public void visit_aupdate(final Instruction inst) {
2416:                final Integer operand = (Integer) inst.operand();
2417:                addOpcode(Opcode.opc_aupdate);
2418:                addByte(operand.intValue());
2419:                stackHeight += 0;
2420:            }
2421:
2422:            public void visit_supdate(final Instruction inst) {
2423:                final Integer operand = (Integer) inst.operand();
2424:                addOpcode(Opcode.opc_supdate);
2425:                addByte(operand.intValue());
2426:                stackHeight += 0;
2427:            }
2428:
2429:            /**
2430:             * Represents the height of the stack at given Label.
2431:             */
2432:            class HeightRecord {
2433:                Label label;
2434:
2435:                int height;
2436:
2437:                public HeightRecord(final Label label, final int height) {
2438:                    if (ClassEditor.DEBUG || CodeArray.DEBUG) {
2439:                        System.out.println("    push " + label + " at "
2440:                                + height);
2441:                    }
2442:
2443:                    this .label = label;
2444:                    this .height = height;
2445:                }
2446:            }
2447:
2448:            /**
2449:             * Used to represent the byte array.
2450:             */
2451:            class ByteCell {
2452:                byte value;
2453:
2454:                ByteCell prev;
2455:            }
2456:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.