Source Code Cross Referenced for Tree.java in  » Database-DBMS » db4o-6.4 » EDU » purdue » cs » bloat » tree » 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.tree 
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.tree;
0022:
0023:        import java.util.*;
0024:
0025:        import EDU.purdue.cs.bloat.cfg.*;
0026:        import EDU.purdue.cs.bloat.editor.*;
0027:        import EDU.purdue.cs.bloat.reflect.*;
0028:        import EDU.purdue.cs.bloat.util.*;
0029:
0030:        /**
0031:         * Tree represents the expression tree of a basic Block. It consists of an
0032:         * operand (expression) stack comprised of expressions and a list of statements
0033:         * contained in the block.
0034:         * 
0035:         * @see Block
0036:         * @see Expr
0037:         * @see OperandStack
0038:         * @see Stmt see StmtList
0039:         */
0040:        public class Tree extends Node implements  InstructionVisitor, Opcode {
0041:            public static boolean DEBUG = false;
0042:
0043:            public static boolean FLATTEN = false;
0044:
0045:            public static boolean USE_STACK = true; // Do we use stack vars?
0046:
0047:            public static boolean AUPDATE_FIX_HACK = false;
0048:
0049:            public static boolean AUPDATE_FIX_HACK_CHANGED = false;
0050:
0051:            public static boolean USE_PERSISTENT = false; // Insert UCExpr by default
0052:
0053:            Block block; // Block that is represented by this Tree
0054:
0055:            Subroutine sub; // The Subroutine that we're currently in
0056:
0057:            Block next; // The Block after this one
0058:
0059:            OperandStack stack; // The program stack for this block
0060:
0061:            StmtList stmts; // The statements in the basic block
0062:
0063:            Stack savedStack;
0064:
0065:            static int stackpos = 0;
0066:
0067:            boolean saveValue; // Do we push a StoreExpr on operand stack?
0068:
0069:            // Some dup instruction combinations cause saveStack to generate
0070:            // temporaries that clobber other temporaries. So, we use nextindex
0071:            // to ensure that a uniquely-name temporary is created by
0072:            // saveStack. Yes, this will introduce a lot of new temporaries,
0073:            // but expression propagation should eliminate a lot of them.
0074:            private int nextIndex = 0;
0075:
0076:            private void db(final String s) {
0077:                if (Tree.DEBUG) {
0078:                    System.out.println(s);
0079:                }
0080:            }
0081:
0082:            /**
0083:             * Constructor.
0084:             * 
0085:             * @param block
0086:             *            The basic Block of code represented in this Tree.
0087:             * @param predStack
0088:             *            The contents of the operand stack from the previous basic
0089:             *            Block.
0090:             */
0091:            public Tree(final Block block, final OperandStack predStack) {
0092:                this .block = block;
0093:
0094:                if (Tree.DEBUG) {
0095:                    System.out.println("    new tree for " + block);
0096:                }
0097:
0098:                stack = new OperandStack();
0099:
0100:                stmts = new StmtList();
0101:
0102:                // The first statement in the Tree is the label indicating the start
0103:                // of the basic Block.
0104:                appendStmt(new LabelStmt(block.label()));
0105:
0106:                // Make a copy of predStack
0107:                for (int i = 0; i < predStack.size(); i++) {
0108:                    final Expr expr = predStack.get(i);
0109:                    final Expr copy = (Expr) expr.clone();
0110:                    copy.setDef(null);
0111:                    stack.push(copy);
0112:                }
0113:            }
0114:
0115:            /**
0116:             * Cleans up this node. Does nothing in this case.
0117:             */
0118:            public void cleanupOnly() {
0119:            }
0120:
0121:            /**
0122:             * Add a Collection of local variables to the block. Add an InitStmt to the
0123:             * statement list.
0124:             * 
0125:             * @see LocalExpr
0126:             * @see InitStmt
0127:             */
0128:            public void initLocals(final Collection locals) {
0129:                final LocalExpr[] t = new LocalExpr[locals.size()];
0130:
0131:                if (t.length == 0) {
0132:                    return;
0133:                }
0134:
0135:                final Iterator iter = locals.iterator();
0136:
0137:                for (int i = 0; iter.hasNext(); i++) {
0138:                    t[i] = (LocalExpr) iter.next();
0139:                }
0140:
0141:                addStmt(new InitStmt(t));
0142:            }
0143:
0144:            /**
0145:             * Removes a statement from the statement list.
0146:             * 
0147:             * @param stmt
0148:             *            The statement to remove
0149:             */
0150:            public void removeStmt(final Stmt stmt) {
0151:                stmts.remove(stmt);
0152:            }
0153:
0154:            /**
0155:             * Removes the last non-Label statement from the statement list.
0156:             */
0157:            public void removeLastStmt() {
0158:                final ListIterator iter = stmts.listIterator(stmts.size());
0159:
0160:                while (iter.hasPrevious()) {
0161:                    final Stmt s = (Stmt) iter.previous();
0162:
0163:                    if (s instanceof  LabelStmt) {
0164:                        continue;
0165:                    }
0166:
0167:                    iter.remove();
0168:                    return;
0169:                }
0170:            }
0171:
0172:            /**
0173:             * @return The statement list
0174:             */
0175:            public List stmts() {
0176:                return stmts;
0177:            }
0178:
0179:            /**
0180:             * StmtList is a linked list of statements. A number of methods are
0181:             * overridden because some adjustments may need to be made to the Nodes in
0182:             * the tree when certain operations are performed.
0183:             */
0184:            class StmtList extends LinkedList {
0185:                /**
0186:                 * Clear the contents of this statement list.
0187:                 */
0188:                public void clear() {
0189:                    final Iterator iter = iterator();
0190:
0191:                    while (iter.hasNext()) {
0192:                        ((Stmt) iter.next()).cleanup();
0193:                    }
0194:
0195:                    super .clear();
0196:                }
0197:
0198:                /**
0199:                 * Remove a statement from the list and clean up afterwards.
0200:                 */
0201:                public boolean remove(final Object o) {
0202:                    if (super .remove(o)) {
0203:                        ((Stmt) o).cleanup();
0204:                        return true;
0205:                    }
0206:
0207:                    return false;
0208:                }
0209:
0210:                /**
0211:                 * Remove all of the statements in a Collection from this statement
0212:                 * list.
0213:                 * 
0214:                 * @param c
0215:                 *            A Collection containing the statements to remove.
0216:                 * @return True, if the contents of this statement list changed.
0217:                 */
0218:                public boolean removeAll(final Collection c) {
0219:                    boolean changed = false;
0220:
0221:                    if (c == this ) {
0222:                        changed = size() > 0;
0223:                        clear();
0224:                    } else {
0225:                        final Iterator iter = c.iterator();
0226:
0227:                        while (iter.hasNext()) {
0228:                            changed = remove(iter.next()) || changed;
0229:                        }
0230:                    }
0231:
0232:                    return changed;
0233:                }
0234:
0235:                /**
0236:                 * Remove all statements in this list except those that are in a
0237:                 * specified Collection.
0238:                 * 
0239:                 * @param c
0240:                 *            The statements to keep.
0241:                 * @return True, if the contents of this statement list changed.
0242:                 */
0243:                public boolean retainAll(final Collection c) {
0244:                    boolean changed = false;
0245:
0246:                    if (c == this ) {
0247:                        return false;
0248:                    }
0249:
0250:                    final Iterator iter = iterator();
0251:
0252:                    while (iter.hasNext()) {
0253:                        if (!c.contains(iter.next())) {
0254:                            changed = true;
0255:                            iter.remove();
0256:                        }
0257:                    }
0258:
0259:                    return changed;
0260:                }
0261:
0262:                /**
0263:                 * Set the value of a given statement.
0264:                 * 
0265:                 * @param index
0266:                 *            Index of the statement to change.
0267:                 * @param element
0268:                 *            New value of statement at index.
0269:                 * 
0270:                 * @return Statement previously at position index.
0271:                 */
0272:                public Object set(final int index, final Object element) {
0273:                    if (index < size()) {
0274:                        final Stmt s = (Stmt) get(index);
0275:
0276:                        if (s != element) {
0277:                            s.cleanup();
0278:                        }
0279:                    }
0280:
0281:                    return super .set(index, element);
0282:                }
0283:
0284:                /**
0285:                 * Removes the statement at index
0286:                 * 
0287:                 * @return Statement previously at position index.
0288:                 */
0289:                public Object remove(final int index) {
0290:                    final Object o = super .remove(index);
0291:
0292:                    if (o != null) {
0293:                        ((Stmt) o).cleanup();
0294:                    }
0295:
0296:                    return o;
0297:                }
0298:
0299:                /**
0300:                 * Removes statements in a given index range.
0301:                 */
0302:                /*
0303:                 * public void removeRange(int fromIndex, int toIndex) { int remaining =
0304:                 * toIndex - fromIndex;
0305:                 * 
0306:                 * ListIterator iter = listIterator(fromIndex);
0307:                 * 
0308:                 * while (iter.hasNext() && remaining-- > 0) { ((Stmt)
0309:                 * iter.next()).cleanup(); }
0310:                 * 
0311:                 * super.removeRange(fromIndex, toIndex); }
0312:                 */
0313:
0314:                /**
0315:                 * @return A ListIterator starting with the first statement in the
0316:                 *         statement list.
0317:                 */
0318:                public ListIterator listIterator() {
0319:                    return listIterator(0);
0320:                }
0321:
0322:                /**
0323:                 * @return A ListIterator starting a given index.
0324:                 */
0325:                public ListIterator listIterator(final int index) {
0326:                    final ListIterator iter = super .listIterator(index);
0327:
0328:                    return new ListIterator() {
0329:                        Object last = null;
0330:
0331:                        public boolean hasNext() {
0332:                            return iter.hasNext();
0333:                        }
0334:
0335:                        public Object next() {
0336:                            last = iter.next();
0337:                            return last;
0338:                        }
0339:
0340:                        public boolean hasPrevious() {
0341:                            return iter.hasPrevious();
0342:                        }
0343:
0344:                        public Object previous() {
0345:                            last = iter.previous();
0346:                            return last;
0347:                        }
0348:
0349:                        public int nextIndex() {
0350:                            return iter.nextIndex();
0351:                        }
0352:
0353:                        public int previousIndex() {
0354:                            return iter.previousIndex();
0355:                        }
0356:
0357:                        public void add(final Object obj) {
0358:                            Assert.isTrue(obj instanceof  Stmt);
0359:                            ((Stmt) obj).setParent(Tree.this );
0360:                            last = null;
0361:                            iter.add(obj);
0362:                        }
0363:
0364:                        public void set(final Object obj) {
0365:                            if (last == null) {
0366:                                throw new NoSuchElementException();
0367:                            }
0368:
0369:                            Assert.isTrue(obj instanceof  Stmt);
0370:                            ((Stmt) obj).setParent(Tree.this );
0371:
0372:                            ((Stmt) last).cleanup();
0373:                            last = null;
0374:
0375:                            iter.set(obj);
0376:                        }
0377:
0378:                        public void remove() {
0379:                            if (last == null) {
0380:                                throw new NoSuchElementException();
0381:                            }
0382:
0383:                            ((Stmt) last).cleanup();
0384:                            last = null;
0385:
0386:                            iter.remove();
0387:                        }
0388:                    };
0389:                }
0390:
0391:                /**
0392:                 * @return An Iterator over this statement list.
0393:                 */
0394:                public Iterator iterator() {
0395:                    final Iterator iter = super .iterator();
0396:
0397:                    return new Iterator() {
0398:                        Object last = null;
0399:
0400:                        public boolean hasNext() {
0401:                            return iter.hasNext();
0402:                        }
0403:
0404:                        public Object next() {
0405:                            last = iter.next();
0406:                            return last;
0407:                        }
0408:
0409:                        public void remove() {
0410:                            if (last == null) {
0411:                                throw new NoSuchElementException();
0412:                            }
0413:
0414:                            ((Stmt) last).cleanup();
0415:                            last = null;
0416:
0417:                            iter.remove();
0418:                        }
0419:                    };
0420:                }
0421:            }
0422:
0423:            /**
0424:             * Returns the last non-Label statement in the statement list.
0425:             */
0426:            public Stmt lastStmt() {
0427:                final ListIterator iter = stmts.listIterator(stmts.size());
0428:
0429:                while (iter.hasPrevious()) {
0430:                    final Stmt s = (Stmt) iter.previous();
0431:
0432:                    if (s instanceof  LabelStmt) {
0433:                        continue;
0434:                    }
0435:
0436:                    return s;
0437:                }
0438:
0439:                return null;
0440:            }
0441:
0442:            /**
0443:             * Returns the operand stack.
0444:             */
0445:            public OperandStack stack() {
0446:                return stack;
0447:            }
0448:
0449:            /**
0450:             * Inserts a statement into the statement list after another given
0451:             * statement.
0452:             * 
0453:             * @param stmt
0454:             *            The statement to add.
0455:             * @param after
0456:             *            The statement after which to add stmt.
0457:             */
0458:            public void addStmtAfter(final Stmt stmt, final Stmt after) {
0459:                if (Tree.DEBUG) {
0460:                    System.out.println("insert: " + stmt + " after " + after);
0461:                }
0462:
0463:                final ListIterator iter = stmts.listIterator();
0464:
0465:                while (iter.hasNext()) {
0466:                    final Stmt s = (Stmt) iter.next();
0467:
0468:                    if (s == after) {
0469:                        iter.add(stmt);
0470:                        stmt.setParent(this );
0471:                        return;
0472:                    }
0473:                }
0474:
0475:                throw new RuntimeException(after + " not found");
0476:            }
0477:
0478:            /**
0479:             * Inserts a statement into the statement list before a specified statement.
0480:             * 
0481:             * @param stmt
0482:             *            The statement to insert
0483:             * @param before
0484:             *            The statement before which to add stmt.
0485:             */
0486:            public void addStmtBefore(final Stmt stmt, final Stmt before) {
0487:                if (Tree.DEBUG) {
0488:                    System.out.println("insert: " + stmt + " before " + before);
0489:                }
0490:
0491:                final ListIterator iter = stmts.listIterator();
0492:
0493:                while (iter.hasNext()) {
0494:                    final Stmt s = (Stmt) iter.next();
0495:
0496:                    if (s == before) {
0497:                        iter.previous();
0498:                        iter.add(stmt);
0499:                        stmt.setParent(this );
0500:                        return;
0501:                    }
0502:                }
0503:
0504:                throw new RuntimeException(before + " not found");
0505:            }
0506:
0507:            /**
0508:             * Add an statement to the statement list before the first non-Label
0509:             * statement.
0510:             * 
0511:             * @param stmt
0512:             *            The statement to add.
0513:             */
0514:            public void prependStmt(final Stmt stmt) {
0515:                if (Tree.DEBUG) {
0516:                    System.out.println("prepend: " + stmt + " in " + block);
0517:                }
0518:
0519:                final ListIterator iter = stmts.listIterator();
0520:
0521:                while (iter.hasNext()) {
0522:                    final Stmt s = (Stmt) iter.next();
0523:
0524:                    if (!(s instanceof  LabelStmt)) {
0525:                        iter.previous();
0526:                        iter.add(stmt);
0527:                        stmt.setParent(this );
0528:                        return;
0529:                    }
0530:                }
0531:
0532:                appendStmt(stmt);
0533:            }
0534:
0535:            /**
0536:             * When we build the expression tree, there may be items left over on the
0537:             * operand stack. We want to save these items. If USE_STACK is true, then we
0538:             * place these items into stack variables. If USE_STACK is false, then we
0539:             * place the items into local variables.
0540:             */
0541:            private void saveStack() {
0542:                int height = 0;
0543:
0544:                for (int i = 0; i < stack.size(); i++) {
0545:                    final Expr expr = stack.get(i);
0546:
0547:                    if (Tree.USE_STACK) {
0548:                        // Save to a stack variable only if we'll create a new
0549:                        // variable there.
0550:                        if (!(expr instanceof  StackExpr)
0551:                                || (((StackExpr) expr).index() != height)) {
0552:
0553:                            final StackExpr target = new StackExpr(height, expr
0554:                                    .type());
0555:
0556:                            // Make a new statement to store the expression that was
0557:                            // part of the stack into memory.
0558:                            final Stmt store = new ExprStmt(new StoreExpr(
0559:                                    target, expr, expr.type()));
0560:
0561:                            appendStmt(store);
0562:
0563:                            final StackExpr copy = (StackExpr) target.clone();
0564:                            copy.setDef(null);
0565:                            stack.set(i, copy);
0566:                        }
0567:
0568:                    } else {
0569:                        if (!(expr instanceof  LocalExpr)
0570:                                || !((LocalExpr) expr).fromStack()
0571:                                || (((LocalExpr) expr).index() != height)) {
0572:
0573:                            final LocalExpr target = newStackLocal(nextIndex++,
0574:                                    expr.type());
0575:
0576:                            final Stmt store = new ExprStmt(new StoreExpr(
0577:                                    target, expr, expr.type()));
0578:
0579:                            appendStmt(store);
0580:
0581:                            final LocalExpr copy = (LocalExpr) target.clone();
0582:                            copy.setDef(null);
0583:                            stack.set(i, copy);
0584:                        }
0585:                    }
0586:
0587:                    height += expr.type().stackHeight();
0588:                }
0589:            }
0590:
0591:            /**
0592:             * Add a statement to this Tree statement list and specify that this is the
0593:             * statement's parent.
0594:             */
0595:            private void appendStmt(final Stmt stmt) {
0596:                if (Tree.DEBUG) {
0597:                    System.out.println("      append: " + stmt);
0598:                }
0599:
0600:                stmt.setParent(this );
0601:                stmts.add(stmt);
0602:            }
0603:
0604:            /**
0605:             * Save the contents of the stack and add stmt to the statement list.
0606:             * 
0607:             * @param stmt
0608:             *            A statement to add to the statement list.
0609:             */
0610:            public void addStmt(final Stmt stmt) {
0611:                saveStack();
0612:                appendStmt(stmt);
0613:            }
0614:
0615:            /**
0616:             * Adds a statement to the statement list before the last jump statement. It
0617:             * is assumed that the last statement in the statement list is a jump
0618:             * statement.
0619:             * 
0620:             * @see JumpStmt
0621:             */
0622:            public void addStmtBeforeJump(final Stmt stmt) {
0623:                final Stmt last = lastStmt();
0624:                Assert.isTrue(last instanceof  JumpStmt, "Last statement of "
0625:                        + block + " is " + last + ", not a jump");
0626:                addStmtBefore(stmt, last);
0627:            }
0628:
0629:            /**
0630:             * Throw a new ClassFormatException with information about method and class
0631:             * that this basic block is in.
0632:             * 
0633:             * @param msg
0634:             *            String description of the exception.
0635:             * 
0636:             * @see ClassFormatException
0637:             */
0638:            private void throwClassFormatException(final String msg) {
0639:                final MethodEditor method = block.graph().method();
0640:
0641:                throw new ClassFormatException("Method "
0642:                        + method.declaringClass().type().className() + "."
0643:                        + method.name() + " " + method.type() + ": " + msg);
0644:            }
0645:
0646:            /**
0647:             * The last instruction we saw. addInst(Instruction) needs this information.
0648:             */
0649:            Instruction last = null;
0650:
0651:            /**
0652:             * Adds an instruction that jumps to another basic block.
0653:             * 
0654:             * @param inst
0655:             *            The instruction to add.
0656:             * @param next
0657:             *            The basic block after the jump. Remember that a jump ends a
0658:             *            basic block.
0659:             * 
0660:             * @see Instruction#isJsr
0661:             * @see Instruction#isConditionalJump
0662:             */
0663:            public void addInstruction(final Instruction inst, final Block next) {
0664:                Assert.isTrue(inst.isJsr() || inst.isConditionalJump(),
0665:                        "Wrong addInstruction called with " + inst);
0666:                Assert.isTrue(next != null, "Null next block for " + inst);
0667:
0668:                this .next = next;
0669:                addInst(inst);
0670:            }
0671:
0672:            /**
0673:             * Adds an instruction that does not change the control flow (a normal
0674:             * instruction).
0675:             * 
0676:             * @param inst
0677:             *            Instruction to add.
0678:             */
0679:            public void addInstruction(final Instruction inst) {
0680:                Assert.isTrue(!inst.isJsr() && !inst.isConditionalJump(),
0681:                        "Wrong addInstruction called with " + inst);
0682:
0683:                this .next = null;
0684:                addInst(inst);
0685:            }
0686:
0687:            /**
0688:             * Add an instruction such as <i>ret</i> or <i>astore</i> that may involve
0689:             * a subroutine.
0690:             * 
0691:             * @param inst
0692:             *            Instruction to add.
0693:             * @param sub
0694:             *            Subroutine in which inst resides. The <i>ret</i> instruction
0695:             *            always resides in a Subroutine. An <i>astore</i> may store
0696:             *            the return address of a subroutine in a local variable.
0697:             * 
0698:             * @see Instruction#isRet
0699:             */
0700:            public void addInstruction(final Instruction inst,
0701:                    final Subroutine sub) {
0702:                Assert.isTrue(inst.isRet()
0703:                        || (inst.opcodeClass() == Opcode.opcx_astore),
0704:                        "Wrong addInstruction called with " + inst);
0705:
0706:                this .sub = sub;
0707:                this .next = null;
0708:                addInst(inst);
0709:            }
0710:
0711:            /**
0712:             * Add a label to the statement list. A label is inserted before a dup
0713:             * statement, but after any other statement.
0714:             * 
0715:             * @param label
0716:             *            Label to add.
0717:             */
0718:            public void addLabel(final Label label) {
0719:                // Add before a dup, but after any other instruction.
0720:                if (last != null) {
0721:                    switch (last.opcodeClass()) {
0722:                    case opcx_dup:
0723:                    case opcx_dup2:
0724:                    case opcx_dup_x1:
0725:                    case opcx_dup2_x1:
0726:                    case opcx_dup_x2:
0727:                    case opcx_dup2_x2:
0728:                        break;
0729:                    default:
0730:                        addInst(last, false);
0731:                        last = null;
0732:                        break;
0733:                    }
0734:                }
0735:
0736:                addStmt(new LabelStmt(label));
0737:            }
0738:
0739:            /**
0740:             * Private method that adds an instruction to the Tree. The visit method of
0741:             * the instruction is called with this tree as the visitor. The instruction,
0742:             * in turn, calls the appropriate method of this for adding the instruction
0743:             * to the statement list.
0744:             * 
0745:             * @param inst
0746:             *            The <tt>Instruction</tt> to add to the <tt>Tree</tt>
0747:             * @param saveValue
0748:             *            Do we save expressions on the operand stack to stack variables
0749:             *            or local variables.
0750:             */
0751:            private void addInst(final Instruction inst, final boolean saveValue) {
0752:                if (Tree.DEBUG) {
0753:                    // Print the contents of the stack
0754:                    for (int i = 0; i < stack.size(); i++) {
0755:                        final Expr exp = stack.peek(i);
0756:                        System.out.println((i > 0 ? "-" + i : " " + i) + ": "
0757:                                + exp);
0758:                    }
0759:                }
0760:
0761:                if (Tree.DEBUG) {
0762:                    System.out
0763:                            .println("    add " + inst + " save=" + saveValue);
0764:                }
0765:
0766:                try {
0767:                    this .saveValue = saveValue;
0768:
0769:                    if (Tree.FLATTEN) {
0770:                        saveStack();
0771:                    }
0772:
0773:                    inst.visit(this );
0774:
0775:                } catch (final EmptyStackException e) {
0776:                    throwClassFormatException("Empty operand stack at " + inst);
0777:                    return;
0778:                }
0779:            }
0780:
0781:            /**
0782:             * Private method that adds an instruction to the tree. Before dispatching
0783:             * the addition off to addInst(Instruction, boolean), it optimizes(?) dup
0784:             * instructions as outlined below:
0785:             */
0786:            // (S0, S1) := dup(X)
0787:            // L := S1 --> use (L := X)
0788:            // use S0
0789:            //
0790:            // (S0, S1, S2) := dup_x1(X, Y)
0791:            // S1.f := S2 --> use (X.f := Y)
0792:            // use S0
0793:            //
0794:            // (S0, S1, S2, S3) := dup_x2(X, Y, Z)
0795:            // S1[S2] := S3 --> use (X[Y] := Z)
0796:            // use S0
0797:            //
0798:            private void addInst(final Instruction inst) {
0799:                // Build the tree, trying to convert dup-stores
0800:
0801:                if (last == null) {
0802:                    last = inst;
0803:
0804:                } else {
0805:                    switch (last.opcodeClass()) {
0806:                    case opcx_dup:
0807:                        switch (inst.opcodeClass()) {
0808:                        case opcx_astore:
0809:                        case opcx_fstore:
0810:                        case opcx_istore:
0811:                        case opcx_putstatic:
0812:                            addInst(inst, true);
0813:                            last = null;
0814:                            break;
0815:                        }
0816:                        break;
0817:                    case opcx_dup2:
0818:                        switch (inst.opcodeClass()) {
0819:                        case opcx_dstore:
0820:                        case opcx_lstore:
0821:                        case opcx_putstatic:
0822:                            addInst(inst, true);
0823:                            last = null;
0824:                            break;
0825:                        }
0826:                        break;
0827:                    case opcx_dup_x1:
0828:                        switch (inst.opcodeClass()) {
0829:                        case opcx_putfield:
0830:                        case opcx_putfield_nowb:
0831:                            addInst(inst, true);
0832:                            last = null;
0833:                            break;
0834:                        }
0835:                        break;
0836:                    case opcx_dup2_x1:
0837:                        switch (inst.opcodeClass()) {
0838:                        case opcx_putfield:
0839:                        case opcx_putfield_nowb:
0840:                            addInst(inst, true);
0841:                            last = null;
0842:                            break;
0843:                        }
0844:                        break;
0845:                    case opcx_dup_x2:
0846:                        switch (inst.opcodeClass()) {
0847:                        case opcx_aastore:
0848:                        case opcx_bastore:
0849:                        case opcx_castore:
0850:                        case opcx_fastore:
0851:                        case opcx_iastore:
0852:                        case opcx_sastore:
0853:                            addInst(inst, true);
0854:                            last = null;
0855:                            break;
0856:                        }
0857:                        break;
0858:                    case opcx_dup2_x2:
0859:                        switch (inst.opcodeClass()) {
0860:                        case opcx_dastore:
0861:                        case opcx_lastore:
0862:                            addInst(inst, true);
0863:                            last = null;
0864:                            break;
0865:                        }
0866:                        break;
0867:                    }
0868:
0869:                    if (last != null) {
0870:                        addInst(last, false);
0871:                        last = inst;
0872:                    }
0873:                }
0874:
0875:                // We should have dealt with the old last instruction
0876:                Assert.isTrue((last == null) || (last == inst));
0877:
0878:                if (inst.isJump() || inst.isSwitch() || inst.isThrow()
0879:                        || inst.isReturn() || inst.isJsr() || inst.isRet()) {
0880:                    addInst(inst, false);
0881:                    last = null;
0882:                }
0883:            }
0884:
0885:            /**
0886:             * Returns a new StackExpr for the top of the operand stack.
0887:             */
0888:            public StackExpr newStack(final Type type) {
0889:                return new StackExpr(Tree.stackpos++, type);
0890:            }
0891:
0892:            /**
0893:             * Returns a new LocalExpr that represents an element of the stack. They are
0894:             * created when the USE_STACK flag is not set.
0895:             * 
0896:             * @param index
0897:             *            Stack index of variable.
0898:             * @param type
0899:             *            The type of the LocalExpr
0900:             */
0901:            public LocalExpr newStackLocal(final int index, final Type type) {
0902:                if (index >= nextIndex) {
0903:                    nextIndex = index + 1;
0904:                }
0905:                return new LocalExpr(index, true, type);
0906:            }
0907:
0908:            /**
0909:             * Returns a new LocalExpr that is not allocated on the stack.
0910:             * 
0911:             * @param index
0912:             *            Stack index of variable.
0913:             * @param type
0914:             *            The type of the LocalExpr
0915:             */
0916:            public LocalExpr newLocal(final int index, final Type type) {
0917:                return new LocalExpr(index, false, type);
0918:            }
0919:
0920:            /**
0921:             * Returns a local variable (<tt>LocalExpr</tt>) located in this method.
0922:             * 
0923:             * @param type
0924:             *            The type of the new LocalExpr.
0925:             */
0926:            public LocalExpr newLocal(final Type type) {
0927:                final LocalVariable var = block.graph().method().newLocal(type);
0928:                return new LocalExpr(var.index(), type);
0929:            }
0930:
0931:            /**
0932:             * Returns a String representation of this Tree.
0933:             */
0934:            public String toString() {
0935:                String x = "(TREE " + block + " stack=";
0936:
0937:                for (int i = 0; i < stack.size(); i++) {
0938:                    final Expr expr = stack.get(i);
0939:                    x += expr.type().shortName();
0940:                }
0941:
0942:                return x + ")";
0943:            }
0944:
0945:            /**
0946:             * Adds no statements to the statement list.
0947:             */
0948:            public void visit_nop(final Instruction inst) {
0949:            }
0950:
0951:            /**
0952:             * Pushes a ConstantExpr onto the operand stack.
0953:             * 
0954:             * @see ConstantExpr
0955:             */
0956:            public void visit_ldc(final Instruction inst) {
0957:                final Object value = inst.operand();
0958:                Type type;
0959:
0960:                if (value == null) {
0961:                    type = Type.NULL;
0962:                } else if (value instanceof  Integer) {
0963:                    type = Type.INTEGER;
0964:                } else if (value instanceof  Long) {
0965:                    type = Type.LONG;
0966:                } else if (value instanceof  Float) {
0967:                    type = Type.FLOAT;
0968:                } else if (value instanceof  Double) {
0969:                    type = Type.DOUBLE;
0970:                } else if (value instanceof  String) {
0971:                    type = Type.STRING;
0972:                }
0973:                // FIXME this won't work - check usages
0974:                else if (value instanceof  Type) {
0975:                    type = Type.CLASS;
0976:                } else {
0977:                    throwClassFormatException("Illegal constant type: "
0978:                            + value.getClass().getName() + ": " + value);
0979:                    return;
0980:                }
0981:
0982:                final Expr top = new ConstantExpr(value, type);
0983:                stack.push(top);
0984:            }
0985:
0986:            /**
0987:             * All <tt>visit_<i>x</i>load</tt> push a LocalExpr onto the operand
0988:             * stack.
0989:             * 
0990:             * @see LocalExpr
0991:             */
0992:            public void visit_iload(final Instruction inst) {
0993:                final LocalVariable operand = (LocalVariable) inst.operand();
0994:                final Expr top = new LocalExpr(operand.index(), Type.INTEGER);
0995:                stack.push(top);
0996:            }
0997:
0998:            public void visit_lload(final Instruction inst) {
0999:                final LocalVariable operand = (LocalVariable) inst.operand();
1000:                final Expr top = new LocalExpr(operand.index(), Type.LONG);
1001:                stack.push(top);
1002:            }
1003:
1004:            public void visit_fload(final Instruction inst) {
1005:                final LocalVariable operand = (LocalVariable) inst.operand();
1006:                final Expr top = new LocalExpr(operand.index(), Type.FLOAT);
1007:                stack.push(top);
1008:            }
1009:
1010:            public void visit_dload(final Instruction inst) {
1011:                final LocalVariable operand = (LocalVariable) inst.operand();
1012:                final Expr top = new LocalExpr(operand.index(), Type.DOUBLE);
1013:                stack.push(top);
1014:            }
1015:
1016:            public void visit_aload(final Instruction inst) {
1017:                final LocalVariable operand = (LocalVariable) inst.operand();
1018:                final Expr top = new LocalExpr(operand.index(), Type.OBJECT);
1019:                stack.push(top);
1020:
1021:                db("      aload: " + top);
1022:            }
1023:
1024:            /**
1025:             * All <tt>visit_<i>x</i>aload</tt> push an ArrayRefExpr onto the
1026:             * operand stack.
1027:             */
1028:            public void visit_iaload(final Instruction inst) {
1029:                final Expr index = stack.pop(Type.INTEGER);
1030:                final Expr array = stack.pop(Type.INTEGER.arrayType());
1031:                final Expr top = new ArrayRefExpr(array, index, Type.INTEGER,
1032:                        Type.INTEGER);
1033:                stack.push(top);
1034:            }
1035:
1036:            public void visit_laload(final Instruction inst) {
1037:                final Expr index = stack.pop(Type.INTEGER);
1038:                final Expr array = stack.pop(Type.LONG.arrayType());
1039:                final Expr top = new ArrayRefExpr(array, index, Type.LONG,
1040:                        Type.LONG);
1041:                stack.push(top);
1042:            }
1043:
1044:            public void visit_faload(final Instruction inst) {
1045:                final Expr index = stack.pop(Type.INTEGER);
1046:                final Expr array = stack.pop(Type.FLOAT.arrayType());
1047:                final Expr top = new ArrayRefExpr(array, index, Type.FLOAT,
1048:                        Type.FLOAT);
1049:                stack.push(top);
1050:            }
1051:
1052:            public void visit_daload(final Instruction inst) {
1053:                final Expr index = stack.pop(Type.INTEGER);
1054:                final Expr array = stack.pop(Type.DOUBLE.arrayType());
1055:                final Expr top = new ArrayRefExpr(array, index, Type.DOUBLE,
1056:                        Type.DOUBLE);
1057:                stack.push(top);
1058:            }
1059:
1060:            public void visit_aaload(final Instruction inst) {
1061:                final Expr index = stack.pop(Type.INTEGER);
1062:                final Expr array = stack.pop(Type.OBJECT.arrayType());
1063:                final Expr top = new ArrayRefExpr(array, index, Type.OBJECT,
1064:                        Type.OBJECT);
1065:                stack.push(top);
1066:            }
1067:
1068:            public void visit_baload(final Instruction inst) {
1069:                final Expr index = stack.pop(Type.INTEGER);
1070:                final Expr array = stack.pop(Type.BYTE.arrayType());
1071:                final Expr top = new ArrayRefExpr(array, index, Type.BYTE,
1072:                        Type.BYTE);
1073:                stack.push(top);
1074:            }
1075:
1076:            public void visit_caload(final Instruction inst) {
1077:                final Expr index = stack.pop(Type.INTEGER);
1078:                final Expr array = stack.pop(Type.CHARACTER.arrayType());
1079:                final Expr top = new ArrayRefExpr(array, index, Type.CHARACTER,
1080:                        Type.CHARACTER);
1081:                stack.push(top);
1082:            }
1083:
1084:            public void visit_saload(final Instruction inst) {
1085:                final Expr index = stack.pop(Type.INTEGER);
1086:                final Expr array = stack.pop(Type.SHORT.arrayType());
1087:                final Expr top = new ArrayRefExpr(array, index, Type.SHORT,
1088:                        Type.SHORT);
1089:                stack.push(top);
1090:            }
1091:
1092:            /**
1093:             * Deals with an expression that stores a value. It either pushes it on the
1094:             * operand stack or adds a statement depending on the value of saveValue.
1095:             * 
1096:             * @param target
1097:             *            The location to where we are storing the value.
1098:             * @param expr
1099:             *            The expression whose value we are storing.
1100:             */
1101:            private void addStore(final MemExpr target, final Expr expr) {
1102:                if (saveValue) {
1103:                    stack.push(new StoreExpr(target, expr, expr.type()));
1104:
1105:                } else {
1106:                    addStmt(new ExprStmt(new StoreExpr(target, expr, expr
1107:                            .type())));
1108:                }
1109:            }
1110:
1111:            /**
1112:             * All <tt>visit_<i>x</i>store</tt> add a LocalExpr statement to the
1113:             * statement list.
1114:             */
1115:            public void visit_istore(final Instruction inst) {
1116:                final LocalVariable operand = (LocalVariable) inst.operand();
1117:                final Expr expr = stack.pop(Type.INTEGER);
1118:                final LocalExpr target = new LocalExpr(operand.index(), expr
1119:                        .type());
1120:                addStore(target, expr);
1121:            }
1122:
1123:            public void visit_lstore(final Instruction inst) {
1124:                final LocalVariable operand = (LocalVariable) inst.operand();
1125:                final Expr expr = stack.pop(Type.LONG);
1126:                final LocalExpr target = new LocalExpr(operand.index(), expr
1127:                        .type());
1128:                addStore(target, expr);
1129:            }
1130:
1131:            public void visit_fstore(final Instruction inst) {
1132:                final LocalVariable operand = (LocalVariable) inst.operand();
1133:                final Expr expr = stack.pop(Type.FLOAT);
1134:                final LocalExpr target = new LocalExpr(operand.index(), expr
1135:                        .type());
1136:                addStore(target, expr);
1137:            }
1138:
1139:            public void visit_dstore(final Instruction inst) {
1140:                final LocalVariable operand = (LocalVariable) inst.operand();
1141:                final Expr expr = stack.pop(Type.DOUBLE);
1142:                final LocalExpr target = new LocalExpr(operand.index(), expr
1143:                        .type());
1144:                addStore(target, expr);
1145:            }
1146:
1147:            /**
1148:             * Visit an <i>astore</i> instruction. If the type of the operand to the
1149:             * instruction is an address add an AddressStoreStmt to the tree, else add a
1150:             * StoreStmt to the tree consisting of a LocalExpr and the top Expr on the
1151:             * operand stack.
1152:             * 
1153:             * @see AddressStoreStmt
1154:             * @see LocalExpr
1155:             * @see StoreExpr
1156:             */
1157:            public void visit_astore(final Instruction inst) {
1158:                final LocalVariable operand = (LocalVariable) inst.operand();
1159:
1160:                Expr expr = stack.peek();
1161:
1162:                if (expr.type().isAddress()) {
1163:                    Assert.isTrue(sub != null);
1164:                    Assert.isTrue(!saveValue);
1165:                    expr = stack.pop(Type.ADDRESS);
1166:                    sub.setReturnAddress(operand);
1167:                    addStmt(new AddressStoreStmt(sub));
1168:                } else {
1169:                    expr = stack.pop(Type.OBJECT);
1170:                    final LocalExpr target = new LocalExpr(operand.index(),
1171:                            expr.type());
1172:                    addStore(target, expr);
1173:                }
1174:            }
1175:
1176:            public void visit_iastore(final Instruction inst) {
1177:                final Expr value = stack.pop(Type.INTEGER);
1178:                final Expr index = stack.pop(Type.INTEGER);
1179:                final Expr array = stack.pop(Type.INTEGER.arrayType());
1180:                final ArrayRefExpr target = new ArrayRefExpr(array, index,
1181:                        Type.INTEGER, Type.INTEGER);
1182:                addStore(target, value);
1183:            }
1184:
1185:            public void visit_lastore(final Instruction inst) {
1186:                final Expr value = stack.pop(Type.LONG);
1187:                final Expr index = stack.pop(Type.INTEGER);
1188:                final Expr array = stack.pop(Type.LONG.arrayType());
1189:                final ArrayRefExpr target = new ArrayRefExpr(array, index,
1190:                        Type.LONG, Type.LONG);
1191:                addStore(target, value);
1192:            }
1193:
1194:            public void visit_fastore(final Instruction inst) {
1195:                final Expr value = stack.pop(Type.FLOAT);
1196:                final Expr index = stack.pop(Type.INTEGER);
1197:                final Expr array = stack.pop(Type.FLOAT.arrayType());
1198:                final ArrayRefExpr target = new ArrayRefExpr(array, index,
1199:                        Type.FLOAT, Type.FLOAT);
1200:                addStore(target, value);
1201:            }
1202:
1203:            public void visit_dastore(final Instruction inst) {
1204:                final Expr value = stack.pop(Type.DOUBLE);
1205:                final Expr index = stack.pop(Type.INTEGER);
1206:                final Expr array = stack.pop(Type.DOUBLE.arrayType());
1207:                final ArrayRefExpr target = new ArrayRefExpr(array, index,
1208:                        Type.DOUBLE, Type.DOUBLE);
1209:                addStore(target, value);
1210:            }
1211:
1212:            public void visit_aastore(final Instruction inst) {
1213:                final Expr value = stack.pop(Type.OBJECT);
1214:                final Expr index = stack.pop(Type.INTEGER);
1215:                final Expr array = stack.pop(Type.OBJECT.arrayType());
1216:                final ArrayRefExpr target = new ArrayRefExpr(array, index,
1217:                        Type.OBJECT, Type.OBJECT);
1218:                addStore(target, value);
1219:            }
1220:
1221:            public void visit_bastore(final Instruction inst) {
1222:                final Expr value = stack.pop(Type.BYTE);
1223:                final Expr index = stack.pop(Type.INTEGER);
1224:                final Expr array = stack.pop(Type.BYTE.arrayType());
1225:                final ArrayRefExpr target = new ArrayRefExpr(array, index,
1226:                        Type.BYTE, Type.BYTE);
1227:                addStore(target, value);
1228:            }
1229:
1230:            public void visit_castore(final Instruction inst) {
1231:                final Expr value = stack.pop(Type.CHARACTER);
1232:                final Expr index = stack.pop(Type.INTEGER);
1233:                final Expr array = stack.pop(Type.CHARACTER.arrayType());
1234:                final ArrayRefExpr target = new ArrayRefExpr(array, index,
1235:                        Type.CHARACTER, Type.CHARACTER);
1236:                addStore(target, value);
1237:            }
1238:
1239:            public void visit_sastore(final Instruction inst) {
1240:                final Expr value = stack.pop(Type.SHORT);
1241:                final Expr index = stack.pop(Type.INTEGER);
1242:                final Expr array = stack.pop(Type.SHORT.arrayType());
1243:                final ArrayRefExpr target = new ArrayRefExpr(array, index,
1244:                        Type.SHORT, Type.SHORT);
1245:                addStore(target, value);
1246:            }
1247:
1248:            /**
1249:             * Pop the expression off the top of the stack and add it as an ExprStmt to
1250:             * the statement list.
1251:             * 
1252:             * @see ExprStmt
1253:             */
1254:            public void visit_pop(final Instruction inst) {
1255:                final Expr expr = stack.pop1();
1256:                addStmt(new ExprStmt(expr));
1257:            }
1258:
1259:            public void visit_pop2(final Instruction inst) {
1260:                final Expr[] expr = stack.pop2();
1261:
1262:                if (expr.length == 1) {
1263:                    addStmt(new ExprStmt(expr[0]));
1264:                } else {
1265:                    addStmt(new ExprStmt(expr[0]));
1266:                    addStmt(new ExprStmt(expr[1]));
1267:                }
1268:            }
1269:
1270:            /**
1271:             * When processing the <i>dup</i> instructions one of two situations can
1272:             * occur. If the <tt>USE_STACK</tt> flag is set, then a StackManipStmt is
1273:             * created to represent the transformation that the <i>dup</i> instruction
1274:             * performs on the stack. If the <tt>USE_STACK</tt> flag is not set, then
1275:             * the transformation is simulated by creating new local variables
1276:             * containing the appropriate element of the stack.
1277:             * 
1278:             * @see LocalExpr
1279:             * @see StackExpr
1280:             * @see StackManipStmt
1281:             */
1282:            public void visit_dup(final Instruction inst) {
1283:                // 0 -> 0 0
1284:
1285:                db("      dup");
1286:
1287:                if (Tree.USE_STACK) {
1288:                    saveStack();
1289:
1290:                    final StackExpr s0 = (StackExpr) stack.pop1();
1291:
1292:                    final StackExpr[] s = new StackExpr[] { s0 };
1293:                    manip(s, new int[] { 0, 0 }, StackManipStmt.DUP);
1294:
1295:                } else {
1296:                    final Expr s0 = stack.pop1();
1297:
1298:                    final LocalExpr t0 = newStackLocal(stack.height(), s0
1299:                            .type());
1300:
1301:                    db("        s0: " + s0);
1302:                    db("        t0: " + t0);
1303:
1304:                    if (!t0.equalsExpr(s0)) {
1305:                        db("          t0 <- s0");
1306:                        addStore(t0, s0);
1307:                    }
1308:
1309:                    Expr copy = (Expr) t0.clone();
1310:                    copy.setDef(null);
1311:                    stack.push(copy);
1312:
1313:                    copy = (Expr) t0.clone();
1314:                    copy.setDef(null);
1315:                    stack.push(copy);
1316:                }
1317:            }
1318:
1319:            public void visit_dup_x1(final Instruction inst) {
1320:                // 0 1 -> 1 0 1
1321:
1322:                if (Tree.USE_STACK) {
1323:                    saveStack();
1324:
1325:                    final StackExpr s1 = (StackExpr) stack.pop1();
1326:                    final StackExpr s0 = (StackExpr) stack.pop1();
1327:
1328:                    final StackExpr[] s = new StackExpr[] { s0, s1 };
1329:                    manip(s, new int[] { 1, 0, 1 }, StackManipStmt.DUP_X1);
1330:
1331:                } else {
1332:                    final Expr s1 = stack.pop1();
1333:                    final Expr s0 = stack.pop1();
1334:
1335:                    final LocalExpr t0 = newStackLocal(stack.height(), s0
1336:                            .type());
1337:                    final LocalExpr t1 = newStackLocal(stack.height() + 1, s1
1338:                            .type());
1339:
1340:                    if (!t0.equalsExpr(s0)) {
1341:                        addStore(t0, s0);
1342:                    }
1343:
1344:                    if (!t1.equalsExpr(s1)) {
1345:                        addStore(t1, s1);
1346:                    }
1347:
1348:                    Expr copy = (Expr) t1.clone();
1349:                    copy.setDef(null);
1350:                    stack.push(copy);
1351:
1352:                    copy = (Expr) t0.clone();
1353:                    copy.setDef(null);
1354:                    stack.push(copy);
1355:
1356:                    copy = (Expr) t1.clone();
1357:                    copy.setDef(null);
1358:                    stack.push(copy);
1359:                }
1360:            }
1361:
1362:            public void visit_dup_x2(final Instruction inst) {
1363:                // 0 1 2 -> 2 0 1 2
1364:                // 0-1 2 -> 2 0-1 2
1365:
1366:                db("      dup_x2");
1367:
1368:                if (Tree.USE_STACK) {
1369:                    saveStack();
1370:
1371:                    final StackExpr s2 = (StackExpr) stack.pop1();
1372:                    final Expr[] s01 = stack.pop2();
1373:
1374:                    if (s01.length == 2) {
1375:                        // 0 1 2 -> 2 0 1 2
1376:                        final StackExpr[] s = new StackExpr[] {
1377:                                (StackExpr) s01[0], (StackExpr) s01[1], s2 };
1378:                        manip(s, new int[] { 2, 0, 1, 2 },
1379:                                StackManipStmt.DUP_X2);
1380:                    } else {
1381:                        // 0-1 2 -> 2 0-1 2
1382:                        final StackExpr[] s = new StackExpr[] {
1383:                                (StackExpr) s01[0], s2 };
1384:                        manip(s, new int[] { 1, 0, 1 }, StackManipStmt.DUP_X2);
1385:                    }
1386:
1387:                } else {
1388:                    final Expr s2 = stack.pop1();
1389:                    final Expr[] s01 = stack.pop2();
1390:
1391:                    db("        s2: " + s2);
1392:                    db("        s01: " + s01[0]
1393:                            + (s01.length > 1 ? " " + s01[1] : ""));
1394:
1395:                    if (s01.length == 2) {
1396:                        // 0 1 2 -> 2 0 1 2
1397:                        final LocalExpr t0 = newStackLocal(stack.height(),
1398:                                s01[0].type());
1399:                        final LocalExpr t1 = newStackLocal(stack.height() + 1,
1400:                                s01[1].type());
1401:                        final LocalExpr t2 = newStackLocal(stack.height() + 2,
1402:                                s2.type());
1403:
1404:                        db("        t0: " + t0);
1405:                        db("        t1: " + t1);
1406:                        db("        t2: " + t2);
1407:
1408:                        if (!t0.equalsExpr(s01[0])) {
1409:                            db("          t0 <- s01[0]");
1410:                            addStore(t0, s01[0]);
1411:                        }
1412:
1413:                        if (!t1.equalsExpr(s01[1])) {
1414:                            db("          t1 <- s01[1]");
1415:                            addStore(t1, s01[1]);
1416:                        }
1417:
1418:                        if (!t2.equalsExpr(s2)) {
1419:                            db("          t2 <- s2");
1420:                            addStore(t2, s2);
1421:                        }
1422:
1423:                        Expr copy = (Expr) t2.clone();
1424:                        copy.setDef(null);
1425:                        stack.push(copy);
1426:
1427:                        copy = (Expr) t0.clone();
1428:                        copy.setDef(null);
1429:                        stack.push(copy);
1430:
1431:                        copy = (Expr) t1.clone();
1432:                        copy.setDef(null);
1433:                        stack.push(copy);
1434:
1435:                        copy = (Expr) t2.clone();
1436:                        copy.setDef(null);
1437:                        stack.push(copy);
1438:
1439:                    } else {
1440:                        // 0-1 2 -> 2 0-1 2
1441:                        final LocalExpr t0 = newStackLocal(stack.height(),
1442:                                s01[0].type());
1443:                        final LocalExpr t2 = newStackLocal(stack.height() + 2,
1444:                                s2.type());
1445:
1446:                        if (!t0.equalsExpr(s01[0])) {
1447:                            addStore(t0, s01[0]);
1448:                        }
1449:
1450:                        if (!t2.equalsExpr(s2)) {
1451:                            addStore(t2, s2);
1452:                        }
1453:
1454:                        Expr copy = (Expr) t2.clone();
1455:                        copy.setDef(null);
1456:                        stack.push(copy);
1457:
1458:                        copy = (Expr) t0.clone();
1459:                        copy.setDef(null);
1460:                        stack.push(copy);
1461:
1462:                        copy = (Expr) t2.clone();
1463:                        copy.setDef(null);
1464:                        stack.push(copy);
1465:                    }
1466:                }
1467:            }
1468:
1469:            public void visit_dup2(final Instruction inst) {
1470:                // 0 1 -> 0 1 0 1
1471:                // 0-1 -> 0-1 0-1
1472:
1473:                if (Tree.USE_STACK) {
1474:                    saveStack();
1475:
1476:                    final Expr[] s01 = stack.pop2();
1477:
1478:                    if (s01.length == 1) {
1479:                        // 0-1 -> 0-1 0-1
1480:                        final StackExpr[] s = new StackExpr[] { (StackExpr) s01[0] };
1481:                        manip(s, new int[] { 0, 0 }, StackManipStmt.DUP2);
1482:                    } else {
1483:                        // 0 1 -> 0 1 0 1
1484:
1485:                        Assert.isTrue(s01.length == 2);
1486:
1487:                        final StackExpr[] s = new StackExpr[] {
1488:                                (StackExpr) s01[0], (StackExpr) s01[1] };
1489:                        manip(s, new int[] { 0, 1, 0, 1 }, StackManipStmt.DUP2);
1490:                    }
1491:                } else {
1492:                    final Expr[] s01 = stack.pop2();
1493:
1494:                    if (s01.length == 1) {
1495:                        // 0-1 -> 0-1 0-1
1496:                        final LocalExpr t0 = newStackLocal(stack.height(),
1497:                                s01[0].type());
1498:
1499:                        if (!t0.equalsExpr(s01[0])) {
1500:                            addStore(t0, s01[0]);
1501:                        }
1502:
1503:                        Expr copy = (Expr) t0.clone();
1504:                        copy.setDef(null);
1505:                        stack.push(copy);
1506:
1507:                        copy = (Expr) t0.clone();
1508:                        copy.setDef(null);
1509:                        stack.push(copy);
1510:                    } else {
1511:                        // 0 1 -> 0 1 0 1
1512:                        final LocalExpr t0 = newStackLocal(stack.height(),
1513:                                s01[0].type());
1514:                        final LocalExpr t1 = newStackLocal(stack.height() + 1,
1515:                                s01[1].type());
1516:
1517:                        if (!t0.equalsExpr(s01[0])) {
1518:                            addStore(t0, s01[0]);
1519:                        }
1520:
1521:                        if (!t1.equalsExpr(s01[1])) {
1522:                            addStore(t1, s01[1]);
1523:                        }
1524:
1525:                        Expr copy = (Expr) t0.clone();
1526:                        copy.setDef(null);
1527:                        stack.push(copy);
1528:
1529:                        copy = (Expr) t1.clone();
1530:                        copy.setDef(null);
1531:                        stack.push(copy);
1532:
1533:                        copy = (Expr) t0.clone();
1534:                        copy.setDef(null);
1535:                        stack.push(copy);
1536:
1537:                        copy = (Expr) t1.clone();
1538:                        copy.setDef(null);
1539:                        stack.push(copy);
1540:                    }
1541:                }
1542:            }
1543:
1544:            public void visit_dup2_x1(final Instruction inst) {
1545:                // 0 1 2 -> 1 2 0 1 2
1546:                // 0 1-2 -> 1-2 0 1-2
1547:
1548:                if (Tree.USE_STACK) {
1549:                    saveStack();
1550:
1551:                    final Expr[] s12 = stack.pop2();
1552:                    final StackExpr s0 = (StackExpr) stack.pop1();
1553:
1554:                    if (s12.length == 2) {
1555:                        // 0 1 2 -> 1 2 0 1 2
1556:                        final StackExpr[] s = new StackExpr[] { s0,
1557:                                (StackExpr) s12[0], (StackExpr) s12[1] };
1558:                        manip(s, new int[] { 1, 2, 0, 1, 2 },
1559:                                StackManipStmt.DUP2_X1);
1560:                    } else {
1561:                        // 0 1-2 -> 1-2 0 1-2
1562:                        final StackExpr[] s = new StackExpr[] { s0,
1563:                                (StackExpr) s12[0] };
1564:                        manip(s, new int[] { 1, 0, 1 }, StackManipStmt.DUP2_X1);
1565:                    }
1566:                } else {
1567:                    final Expr[] s12 = stack.pop2();
1568:                    final StackExpr s0 = (StackExpr) stack.pop1();
1569:
1570:                    if (s12.length == 2) {
1571:                        // 0 1 2 -> 1 2 0 1 2
1572:                        final LocalExpr t0 = newStackLocal(stack.height(), s0
1573:                                .type());
1574:                        final LocalExpr t1 = newStackLocal(stack.height() + 1,
1575:                                s12[0].type());
1576:                        final LocalExpr t2 = newStackLocal(stack.height() + 2,
1577:                                s12[1].type());
1578:
1579:                        if (!t0.equalsExpr(s0)) {
1580:                            addStore(t0, s0);
1581:                        }
1582:
1583:                        if (!t1.equalsExpr(s12[0])) {
1584:                            addStore(t1, s12[0]);
1585:                        }
1586:
1587:                        if (!t2.equalsExpr(s12[1])) {
1588:                            addStore(t2, s12[1]);
1589:                        }
1590:
1591:                        Expr copy = (Expr) t1.clone();
1592:                        copy.setDef(null);
1593:                        stack.push(copy);
1594:
1595:                        copy = (Expr) t2.clone();
1596:                        copy.setDef(null);
1597:                        stack.push(copy);
1598:
1599:                        copy = (Expr) t0.clone();
1600:                        copy.setDef(null);
1601:                        stack.push(copy);
1602:
1603:                        copy = (Expr) t1.clone();
1604:                        copy.setDef(null);
1605:                        stack.push(copy);
1606:
1607:                        copy = (Expr) t2.clone();
1608:                        copy.setDef(null);
1609:                        stack.push(copy);
1610:                    } else {
1611:                        // 0 1-2 -> 1-2 0 1-2
1612:                        final LocalExpr t0 = newStackLocal(stack.height(), s0
1613:                                .type());
1614:                        final LocalExpr t1 = newStackLocal(stack.height() + 1,
1615:                                s12[0].type());
1616:
1617:                        if (!t0.equalsExpr(s0)) {
1618:                            addStore(t0, s0);
1619:                        }
1620:
1621:                        if (!t1.equalsExpr(s12[0])) {
1622:                            addStore(t1, s12[0]);
1623:                        }
1624:
1625:                        Expr copy = (Expr) t1.clone();
1626:                        copy.setDef(null);
1627:                        stack.push(copy);
1628:
1629:                        copy = (Expr) t0.clone();
1630:                        copy.setDef(null);
1631:                        stack.push(copy);
1632:
1633:                        copy = (Expr) t1.clone();
1634:                        copy.setDef(null);
1635:                        stack.push(copy);
1636:                    }
1637:                }
1638:            }
1639:
1640:            public void visit_dup2_x2(final Instruction inst) {
1641:                // 0 1 2 3 -> 2 3 0 1 2 3
1642:                // 0 1 2-3 -> 2-3 0 1 2-3
1643:                // 0-1 2 3 -> 2 3 0-1 2 3
1644:                // 0-1 2-3 -> 2-3 0-1 2-3
1645:
1646:                if (Tree.USE_STACK) {
1647:                    saveStack();
1648:
1649:                    final Expr[] s23 = stack.pop2();
1650:                    final Expr[] s01 = stack.pop2();
1651:
1652:                    if ((s01.length == 2) && (s23.length == 2)) {
1653:                        // 0 1 2 3 -> 2 3 0 1 2 3
1654:                        final StackExpr[] s = new StackExpr[] {
1655:                                (StackExpr) s01[0], (StackExpr) s01[1],
1656:                                (StackExpr) s23[0], (StackExpr) s23[1] };
1657:                        manip(s, new int[] { 2, 3, 0, 1, 2, 3 },
1658:                                StackManipStmt.DUP2_X2);
1659:                    } else if ((s01.length == 2) && (s23.length == 1)) {
1660:                        // 0 1 2-3 -> 2-3 0 1 2-3
1661:                        final StackExpr[] s = new StackExpr[] {
1662:                                (StackExpr) s01[0], (StackExpr) s01[1],
1663:                                (StackExpr) s23[0] };
1664:                        manip(s, new int[] { 2, 0, 1, 2 },
1665:                                StackManipStmt.DUP2_X2);
1666:                    } else if ((s01.length == 1) && (s23.length == 2)) {
1667:                        // 0-1 2 3 -> 2 3 0-1 2 3
1668:                        final StackExpr[] s = new StackExpr[] {
1669:                                (StackExpr) s01[0], (StackExpr) s23[0],
1670:                                (StackExpr) s23[1] };
1671:                        manip(s, new int[] { 1, 2, 0, 1, 2 },
1672:                                StackManipStmt.DUP2_X2);
1673:                    } else if ((s01.length == 1) && (s23.length == 2)) {
1674:                        // 0-1 2-3 -> 2-3 0-1 2-3
1675:                        final StackExpr[] s = new StackExpr[] {
1676:                                (StackExpr) s01[0], (StackExpr) s23[0] };
1677:                        manip(s, new int[] { 1, 0, 1 }, StackManipStmt.DUP2_X2);
1678:                    }
1679:                } else {
1680:                    final Expr[] s23 = stack.pop2();
1681:                    final Expr[] s01 = stack.pop2();
1682:
1683:                    if ((s01.length == 2) && (s23.length == 2)) {
1684:                        // 0 1 2 3 -> 2 3 0 1 2 3
1685:                        final LocalExpr t0 = newStackLocal(stack.height(),
1686:                                s01[0].type());
1687:                        final LocalExpr t1 = newStackLocal(stack.height() + 1,
1688:                                s01[1].type());
1689:                        final LocalExpr t2 = newStackLocal(stack.height() + 2,
1690:                                s23[0].type());
1691:                        final LocalExpr t3 = newStackLocal(stack.height() + 3,
1692:                                s23[1].type());
1693:
1694:                        if (!t0.equalsExpr(s01[0])) {
1695:                            addStore(t0, s01[0]);
1696:                        }
1697:
1698:                        if (!t1.equalsExpr(s01[1])) {
1699:                            addStore(t1, s01[1]);
1700:                        }
1701:
1702:                        if (!t2.equalsExpr(s23[0])) {
1703:                            addStore(t2, s23[0]);
1704:                        }
1705:
1706:                        if (!t3.equalsExpr(s23[1])) {
1707:                            addStore(t3, s23[1]);
1708:                        }
1709:
1710:                        Expr copy = (Expr) t2.clone();
1711:                        copy.setDef(null);
1712:                        stack.push(copy);
1713:
1714:                        copy = (Expr) t3.clone();
1715:                        copy.setDef(null);
1716:                        stack.push(copy);
1717:
1718:                        copy = (Expr) t0.clone();
1719:                        copy.setDef(null);
1720:                        stack.push(copy);
1721:
1722:                        copy = (Expr) t1.clone();
1723:                        copy.setDef(null);
1724:                        stack.push(copy);
1725:
1726:                        copy = (Expr) t2.clone();
1727:                        copy.setDef(null);
1728:                        stack.push(copy);
1729:
1730:                        copy = (Expr) t3.clone();
1731:                        copy.setDef(null);
1732:                        stack.push(copy);
1733:                    } else if ((s01.length == 2) && (s23.length == 1)) {
1734:                        // 0 1 2-3 -> 2-3 0 1 2-3
1735:                        final LocalExpr t0 = newStackLocal(stack.height(),
1736:                                s01[0].type());
1737:                        final LocalExpr t1 = newStackLocal(stack.height() + 1,
1738:                                s01[1].type());
1739:                        final LocalExpr t2 = newStackLocal(stack.height() + 2,
1740:                                s23[0].type());
1741:
1742:                        if (!t0.equalsExpr(s01[0])) {
1743:                            addStore(t0, s01[0]);
1744:                        }
1745:
1746:                        if (!t1.equalsExpr(s01[1])) {
1747:                            addStore(t1, s01[1]);
1748:                        }
1749:
1750:                        if (!t2.equalsExpr(s23[0])) {
1751:                            addStore(t2, s23[0]);
1752:                        }
1753:
1754:                        Expr copy = (Expr) t2.clone();
1755:                        copy.setDef(null);
1756:                        stack.push(copy);
1757:
1758:                        copy = (Expr) t0.clone();
1759:                        copy.setDef(null);
1760:                        stack.push(copy);
1761:
1762:                        copy = (Expr) t1.clone();
1763:                        copy.setDef(null);
1764:                        stack.push(copy);
1765:
1766:                        copy = (Expr) t2.clone();
1767:                        copy.setDef(null);
1768:                        stack.push(copy);
1769:                    } else if ((s01.length == 1) && (s23.length == 2)) {
1770:                        // 0-1 2 3 -> 2 3 0-1 2 3
1771:                        final LocalExpr t0 = newStackLocal(stack.height(),
1772:                                s01[0].type());
1773:                        final LocalExpr t2 = newStackLocal(stack.height() + 2,
1774:                                s23[0].type());
1775:                        final LocalExpr t3 = newStackLocal(stack.height() + 3,
1776:                                s23[1].type());
1777:
1778:                        if (!t0.equalsExpr(s01[0])) {
1779:                            addStore(t0, s01[0]);
1780:                        }
1781:
1782:                        if (!t2.equalsExpr(s23[0])) {
1783:                            addStore(t2, s23[0]);
1784:                        }
1785:
1786:                        if (!t3.equalsExpr(s23[1])) {
1787:                            addStore(t3, s23[1]);
1788:                        }
1789:
1790:                        Expr copy = (Expr) t2.clone();
1791:                        copy.setDef(null);
1792:                        stack.push(copy);
1793:
1794:                        copy = (Expr) t3.clone();
1795:                        copy.setDef(null);
1796:                        stack.push(copy);
1797:
1798:                        copy = (Expr) t0.clone();
1799:                        copy.setDef(null);
1800:                        stack.push(copy);
1801:
1802:                        copy = (Expr) t2.clone();
1803:                        copy.setDef(null);
1804:                        stack.push(copy);
1805:
1806:                        copy = (Expr) t3.clone();
1807:                        copy.setDef(null);
1808:                        stack.push(copy);
1809:                    } else if ((s01.length == 1) && (s23.length == 2)) {
1810:                        // 0-1 2-3 -> 2-3 0-1 2-3
1811:                        final LocalExpr t0 = newStackLocal(stack.height(),
1812:                                s01[0].type());
1813:                        final LocalExpr t2 = newStackLocal(stack.height() + 2,
1814:                                s23[0].type());
1815:
1816:                        if (!t0.equalsExpr(s01[0])) {
1817:                            addStore(t0, s01[0]);
1818:                        }
1819:
1820:                        if (!t2.equalsExpr(s23[0])) {
1821:                            addStore(t2, s23[0]);
1822:                        }
1823:
1824:                        Expr copy = (Expr) t2.clone();
1825:                        copy.setDef(null);
1826:                        stack.push(copy);
1827:
1828:                        copy = (Expr) t0.clone();
1829:                        copy.setDef(null);
1830:                        stack.push(copy);
1831:
1832:                        copy = (Expr) t2.clone();
1833:                        copy.setDef(null);
1834:                        stack.push(copy);
1835:                    }
1836:                }
1837:            }
1838:
1839:            public void visit_swap(final Instruction inst) {
1840:                // 0 1 -> 1 0
1841:
1842:                if (Tree.USE_STACK) {
1843:                    saveStack();
1844:
1845:                    final StackExpr s1 = (StackExpr) stack.pop1();
1846:                    final StackExpr s0 = (StackExpr) stack.pop1();
1847:
1848:                    final StackExpr[] s = new StackExpr[] { s0, s1 };
1849:                    manip(s, new int[] { 1, 0 }, StackManipStmt.SWAP);
1850:                } else {
1851:                    final Expr s1 = stack.pop1();
1852:                    final Expr s0 = stack.pop1();
1853:
1854:                    final LocalExpr t0 = newStackLocal(stack.height(), s0
1855:                            .type());
1856:                    final LocalExpr t1 = newStackLocal(stack.height() + 1, s1
1857:                            .type());
1858:
1859:                    if (!t0.equalsExpr(s0)) {
1860:                        addStore(t0, s0);
1861:                    }
1862:
1863:                    if (!t1.equalsExpr(s1)) {
1864:                        addStore(t1, s1);
1865:                    }
1866:
1867:                    Expr copy = (Expr) t1.clone();
1868:                    copy.setDef(null);
1869:                    stack.push(copy);
1870:
1871:                    copy = (Expr) t0.clone();
1872:                    copy.setDef(null);
1873:                    stack.push(copy);
1874:                }
1875:            }
1876:
1877:            /**
1878:             * Produces a StackManipStmt that represents how the stack is changed as a
1879:             * result of a dup instruction. It should only be used when USE_STACK is
1880:             * true.
1881:             * <p>
1882:             * dup instructions change the top n elements of the JVM stack. This method
1883:             * takes the original top n elements of the stack, an integer array
1884:             * representing the transformation (for instance, if s[0] = 1, then the top
1885:             * element of the new stack should contain the second-from-the-top element
1886:             * of the old stack), and integer representing the dup instruction.
1887:             * 
1888:             * @param source
1889:             *            The interesting part of the stack before the dup instruction
1890:             *            is executed.
1891:             * @param s
1892:             *            An integer array representing the new order of the stack.
1893:             * @param kind
1894:             *            The kind of stack manipulation taking place. (e.g.
1895:             *            StackManipStmt.DUP_X1)
1896:             * 
1897:             * @see StackManipStmt
1898:             */
1899:            private void manip(final StackExpr[] source, final int[] s,
1900:                    final int kind) {
1901:                Assert.isTrue(Tree.USE_STACK);
1902:
1903:                int height = 0; // Height of the stack
1904:
1905:                // Calculate current height of the stack. Recall that the stack
1906:                // elements in source have already been popped off the stack.
1907:                for (int i = 0; i < stack.size(); i++) {
1908:                    final Expr expr = stack.get(i);
1909:                    height += expr.type().stackHeight();
1910:                }
1911:
1912:                // Create the new portion of the stack. Make new StackExpr
1913:                // representing the stack after the dup instruction. Push those
1914:                // new StackExprs onto the operand stack. Finally, create a
1915:                // StackManipStmt that represent the transformation of the old
1916:                // stack (before dup instruction) to the new stack (after dup
1917:                // instruction).
1918:                final StackExpr[] target = new StackExpr[s.length];
1919:
1920:                for (int i = 0; i < s.length; i++) {
1921:                    target[i] = new StackExpr(height, source[s[i]].type());
1922:                    final StackExpr copy = (StackExpr) target[i].clone();
1923:                    copy.setDef(null);
1924:                    stack.push(copy);
1925:                    height += target[i].type().stackHeight();
1926:                }
1927:
1928:                appendStmt(new StackManipStmt(target, source, kind));
1929:            }
1930:
1931:            /**
1932:             * All <tt>visit_<i>x</i>add</tt>, <tt>visit_<i>x</i>sub</tt>,
1933:             * <tt>visit_<i>x</i>mul</tt>, <tt>visit_<i>x</i>div</tt>, etc.
1934:             * push an ArithExpr onto the operand stack.
1935:             * 
1936:             * @see ArithExpr
1937:             */
1938:            public void visit_iadd(final Instruction inst) {
1939:                final Expr right = stack.pop(Type.INTEGER);
1940:                final Expr left = stack.pop(Type.INTEGER);
1941:                final Expr top = new ArithExpr(ArithExpr.ADD, left, right,
1942:                        Type.INTEGER);
1943:                stack.push(top);
1944:            }
1945:
1946:            public void visit_ladd(final Instruction inst) {
1947:                final Expr right = stack.pop(Type.LONG);
1948:                final Expr left = stack.pop(Type.LONG);
1949:                final Expr top = new ArithExpr(ArithExpr.ADD, left, right,
1950:                        Type.LONG);
1951:                stack.push(top);
1952:            }
1953:
1954:            public void visit_fadd(final Instruction inst) {
1955:                final Expr right = stack.pop(Type.FLOAT);
1956:                final Expr left = stack.pop(Type.FLOAT);
1957:                final Expr top = new ArithExpr(ArithExpr.ADD, left, right,
1958:                        Type.FLOAT);
1959:                stack.push(top);
1960:            }
1961:
1962:            public void visit_dadd(final Instruction inst) {
1963:                final Expr right = stack.pop(Type.DOUBLE);
1964:                final Expr left = stack.pop(Type.DOUBLE);
1965:                final Expr top = new ArithExpr(ArithExpr.ADD, left, right,
1966:                        Type.DOUBLE);
1967:                stack.push(top);
1968:            }
1969:
1970:            public void visit_isub(final Instruction inst) {
1971:                final Expr right = stack.pop(Type.INTEGER);
1972:                final Expr left = stack.pop(Type.INTEGER);
1973:                final Expr top = new ArithExpr(ArithExpr.SUB, left, right,
1974:                        Type.INTEGER);
1975:                stack.push(top);
1976:            }
1977:
1978:            public void visit_lsub(final Instruction inst) {
1979:                final Expr right = stack.pop(Type.LONG);
1980:                final Expr left = stack.pop(Type.LONG);
1981:                final Expr top = new ArithExpr(ArithExpr.SUB, left, right,
1982:                        Type.LONG);
1983:                stack.push(top);
1984:            }
1985:
1986:            public void visit_fsub(final Instruction inst) {
1987:                final Expr right = stack.pop(Type.FLOAT);
1988:                final Expr left = stack.pop(Type.FLOAT);
1989:                final Expr top = new ArithExpr(ArithExpr.SUB, left, right,
1990:                        Type.FLOAT);
1991:                stack.push(top);
1992:            }
1993:
1994:            public void visit_dsub(final Instruction inst) {
1995:                final Expr right = stack.pop(Type.DOUBLE);
1996:                final Expr left = stack.pop(Type.DOUBLE);
1997:                final Expr top = new ArithExpr(ArithExpr.SUB, left, right,
1998:                        Type.DOUBLE);
1999:                stack.push(top);
2000:            }
2001:
2002:            public void visit_imul(final Instruction inst) {
2003:                final Expr right = stack.pop(Type.INTEGER);
2004:                final Expr left = stack.pop(Type.INTEGER);
2005:                final Expr top = new ArithExpr(ArithExpr.MUL, left, right,
2006:                        Type.INTEGER);
2007:                stack.push(top);
2008:            }
2009:
2010:            public void visit_lmul(final Instruction inst) {
2011:                final Expr right = stack.pop(Type.LONG);
2012:                final Expr left = stack.pop(Type.LONG);
2013:                final Expr top = new ArithExpr(ArithExpr.MUL, left, right,
2014:                        Type.LONG);
2015:                stack.push(top);
2016:            }
2017:
2018:            public void visit_fmul(final Instruction inst) {
2019:                final Expr right = stack.pop(Type.FLOAT);
2020:                final Expr left = stack.pop(Type.FLOAT);
2021:                final Expr top = new ArithExpr(ArithExpr.MUL, left, right,
2022:                        Type.FLOAT);
2023:                stack.push(top);
2024:            }
2025:
2026:            public void visit_dmul(final Instruction inst) {
2027:                final Expr right = stack.pop(Type.DOUBLE);
2028:                final Expr left = stack.pop(Type.DOUBLE);
2029:                final Expr top = new ArithExpr(ArithExpr.MUL, left, right,
2030:                        Type.DOUBLE);
2031:                stack.push(top);
2032:            }
2033:
2034:            public void visit_idiv(final Instruction inst) {
2035:                final Expr right = stack.pop(Type.INTEGER);
2036:                final Expr left = stack.pop(Type.INTEGER);
2037:                final Expr check = new ZeroCheckExpr(right, Type.INTEGER);
2038:                final Expr top = new ArithExpr(ArithExpr.DIV, left, check,
2039:                        Type.INTEGER);
2040:                stack.push(top);
2041:            }
2042:
2043:            public void visit_ldiv(final Instruction inst) {
2044:                final Expr right = stack.pop(Type.LONG);
2045:                final Expr left = stack.pop(Type.LONG);
2046:                final Expr check = new ZeroCheckExpr(right, Type.LONG);
2047:                final Expr top = new ArithExpr(ArithExpr.DIV, left, check,
2048:                        Type.LONG);
2049:                stack.push(top);
2050:            }
2051:
2052:            public void visit_fdiv(final Instruction inst) {
2053:                final Expr right = stack.pop(Type.FLOAT);
2054:                final Expr left = stack.pop(Type.FLOAT);
2055:                final Expr top = new ArithExpr(ArithExpr.DIV, left, right,
2056:                        Type.FLOAT);
2057:                stack.push(top);
2058:            }
2059:
2060:            public void visit_ddiv(final Instruction inst) {
2061:                final Expr right = stack.pop(Type.DOUBLE);
2062:                final Expr left = stack.pop(Type.DOUBLE);
2063:                final Expr top = new ArithExpr(ArithExpr.DIV, left, right,
2064:                        Type.DOUBLE);
2065:                stack.push(top);
2066:            }
2067:
2068:            public void visit_irem(final Instruction inst) {
2069:                final Expr right = stack.pop(Type.INTEGER);
2070:                final Expr left = stack.pop(Type.INTEGER);
2071:                final Expr check = new ZeroCheckExpr(right, Type.INTEGER);
2072:                final Expr top = new ArithExpr(ArithExpr.REM, left, check,
2073:                        Type.INTEGER);
2074:                stack.push(top);
2075:            }
2076:
2077:            public void visit_lrem(final Instruction inst) {
2078:                final Expr right = stack.pop(Type.LONG);
2079:                final Expr left = stack.pop(Type.LONG);
2080:                final Expr check = new ZeroCheckExpr(right, Type.LONG);
2081:                final Expr top = new ArithExpr(ArithExpr.REM, left, check,
2082:                        Type.LONG);
2083:                stack.push(top);
2084:            }
2085:
2086:            public void visit_frem(final Instruction inst) {
2087:                final Expr right = stack.pop(Type.FLOAT);
2088:                final Expr left = stack.pop(Type.FLOAT);
2089:                final Expr top = new ArithExpr(ArithExpr.REM, left, right,
2090:                        Type.FLOAT);
2091:                stack.push(top);
2092:            }
2093:
2094:            public void visit_drem(final Instruction inst) {
2095:                final Expr right = stack.pop(Type.DOUBLE);
2096:                final Expr left = stack.pop(Type.DOUBLE);
2097:                final Expr top = new ArithExpr(ArithExpr.REM, left, right,
2098:                        Type.DOUBLE);
2099:                stack.push(top);
2100:            }
2101:
2102:            /**
2103:             * All <tt>visit_<i>x</i>neg</tt> push a NegExpr onto the stack.
2104:             * 
2105:             * @see NegExpr
2106:             */
2107:            public void visit_ineg(final Instruction inst) {
2108:                final Expr expr = stack.pop(Type.INTEGER);
2109:                final Expr top = new NegExpr(expr, Type.INTEGER);
2110:                stack.push(top);
2111:            }
2112:
2113:            public void visit_lneg(final Instruction inst) {
2114:                final Expr expr = stack.pop(Type.LONG);
2115:                final Expr top = new NegExpr(expr, Type.LONG);
2116:                stack.push(top);
2117:            }
2118:
2119:            public void visit_fneg(final Instruction inst) {
2120:                final Expr expr = stack.pop(Type.FLOAT);
2121:                final Expr top = new NegExpr(expr, Type.FLOAT);
2122:                stack.push(top);
2123:            }
2124:
2125:            public void visit_dneg(final Instruction inst) {
2126:                final Expr expr = stack.pop(Type.DOUBLE);
2127:                final Expr top = new NegExpr(expr, Type.DOUBLE);
2128:                stack.push(top);
2129:            }
2130:
2131:            /**
2132:             * All <tt>visit_<i>x</i>sh<i>d</i></tt> push a ShiftExpr onto the
2133:             * operand stack.
2134:             * 
2135:             * @see ShiftExpr
2136:             */
2137:            public void visit_ishl(final Instruction inst) {
2138:                final Expr right = stack.pop(Type.INTEGER);
2139:                final Expr left = stack.pop(Type.INTEGER);
2140:                final Expr top = new ShiftExpr(ShiftExpr.LEFT, left, right,
2141:                        Type.INTEGER);
2142:                stack.push(top);
2143:            }
2144:
2145:            public void visit_lshl(final Instruction inst) {
2146:                final Expr right = stack.pop(Type.INTEGER);
2147:                final Expr left = stack.pop(Type.LONG);
2148:                final Expr top = new ShiftExpr(ShiftExpr.LEFT, left, right,
2149:                        Type.LONG);
2150:                stack.push(top);
2151:            }
2152:
2153:            public void visit_ishr(final Instruction inst) {
2154:                final Expr right = stack.pop(Type.INTEGER);
2155:                final Expr left = stack.pop(Type.INTEGER);
2156:                final Expr top = new ShiftExpr(ShiftExpr.RIGHT, left, right,
2157:                        Type.INTEGER);
2158:                stack.push(top);
2159:            }
2160:
2161:            public void visit_lshr(final Instruction inst) {
2162:                final Expr right = stack.pop(Type.INTEGER);
2163:                final Expr left = stack.pop(Type.LONG);
2164:                final Expr top = new ShiftExpr(ShiftExpr.RIGHT, left, right,
2165:                        Type.LONG);
2166:                stack.push(top);
2167:            }
2168:
2169:            public void visit_iushr(final Instruction inst) {
2170:                final Expr right = stack.pop(Type.INTEGER);
2171:                final Expr left = stack.pop(Type.INTEGER);
2172:                final Expr top = new ShiftExpr(ShiftExpr.UNSIGNED_RIGHT, left,
2173:                        right, Type.INTEGER);
2174:                stack.push(top);
2175:            }
2176:
2177:            public void visit_lushr(final Instruction inst) {
2178:                final Expr right = stack.pop(Type.INTEGER);
2179:                final Expr left = stack.pop(Type.LONG);
2180:                final Expr top = new ShiftExpr(ShiftExpr.UNSIGNED_RIGHT, left,
2181:                        right, Type.LONG);
2182:                stack.push(top);
2183:            }
2184:
2185:            /**
2186:             * All <tt>visit_<i>x op</i></tt> push an ArithExpr onto the stack.
2187:             * 
2188:             * @see ArithExpr
2189:             */
2190:            public void visit_iand(final Instruction inst) {
2191:                final Expr right = stack.pop(Type.INTEGER);
2192:                final Expr left = stack.pop(Type.INTEGER);
2193:                final Expr top = new ArithExpr(ArithExpr.AND, left, right,
2194:                        Type.INTEGER);
2195:                stack.push(top);
2196:            }
2197:
2198:            public void visit_land(final Instruction inst) {
2199:                final Expr right = stack.pop(Type.LONG);
2200:                final Expr left = stack.pop(Type.LONG);
2201:                final Expr top = new ArithExpr(ArithExpr.AND, left, right,
2202:                        Type.LONG);
2203:                stack.push(top);
2204:            }
2205:
2206:            public void visit_ior(final Instruction inst) {
2207:                final Expr right = stack.pop(Type.INTEGER);
2208:                final Expr left = stack.pop(Type.INTEGER);
2209:                final Expr top = new ArithExpr(ArithExpr.IOR, left, right,
2210:                        Type.INTEGER);
2211:                stack.push(top);
2212:            }
2213:
2214:            public void visit_lor(final Instruction inst) {
2215:                final Expr right = stack.pop(Type.LONG);
2216:                final Expr left = stack.pop(Type.LONG);
2217:                final Expr top = new ArithExpr(ArithExpr.IOR, left, right,
2218:                        Type.LONG);
2219:                stack.push(top);
2220:            }
2221:
2222:            public void visit_ixor(final Instruction inst) {
2223:                final Expr right = stack.pop(Type.INTEGER);
2224:                final Expr left = stack.pop(Type.INTEGER);
2225:                final Expr top = new ArithExpr(ArithExpr.XOR, left, right,
2226:                        Type.INTEGER);
2227:                stack.push(top);
2228:            }
2229:
2230:            public void visit_lxor(final Instruction inst) {
2231:                final Expr right = stack.pop(Type.LONG);
2232:                final Expr left = stack.pop(Type.LONG);
2233:                final Expr top = new ArithExpr(ArithExpr.XOR, left, right,
2234:                        Type.LONG);
2235:                stack.push(top);
2236:            }
2237:
2238:            /**
2239:             * Visiting an iinc involves creating a ConstantExpr, LocalExpr, ArithExpr
2240:             * StoreExpr, and a ExprStmt.
2241:             */
2242:            public void visit_iinc(final Instruction inst) {
2243:                final IncOperand operand = (IncOperand) inst.operand();
2244:                int incr = operand.incr();
2245:
2246:                if (incr < 0) {
2247:                    final Expr right = new ConstantExpr(new Integer(-incr),
2248:                            Type.INTEGER);
2249:                    final Expr left = new LocalExpr(operand.var().index(),
2250:                            Type.INTEGER);
2251:
2252:                    final Expr top = new ArithExpr(ArithExpr.SUB, left, right,
2253:                            Type.INTEGER);
2254:
2255:                    final LocalExpr copy = (LocalExpr) left.clone();
2256:                    copy.setDef(null);
2257:                    addStmt(new ExprStmt(new StoreExpr(copy, top, left.type())));
2258:                } else if (incr > 0) {
2259:                    final Expr right = new ConstantExpr(new Integer(incr),
2260:                            Type.INTEGER);
2261:                    final Expr left = new LocalExpr(operand.var().index(),
2262:                            Type.INTEGER);
2263:
2264:                    final Expr top = new ArithExpr(ArithExpr.ADD, left, right,
2265:                            Type.INTEGER);
2266:
2267:                    final LocalExpr copy = (LocalExpr) left.clone();
2268:                    copy.setDef(null);
2269:                    addStmt(new ExprStmt(new StoreExpr(copy, top, left.type())));
2270:                }
2271:            }
2272:
2273:            /**
2274:             * All cast visitors push a CastExpr onto the operand stack.
2275:             */
2276:            public void visit_i2l(final Instruction inst) {
2277:                final Expr expr = stack.pop(Type.INTEGER);
2278:                final Expr top = new CastExpr(expr, Type.LONG, Type.LONG);
2279:                stack.push(top);
2280:            }
2281:
2282:            public void visit_i2f(final Instruction inst) {
2283:                final Expr expr = stack.pop(Type.INTEGER);
2284:                final Expr top = new CastExpr(expr, Type.FLOAT, Type.FLOAT);
2285:                stack.push(top);
2286:            }
2287:
2288:            public void visit_i2d(final Instruction inst) {
2289:                final Expr expr = stack.pop(Type.INTEGER);
2290:                final Expr top = new CastExpr(expr, Type.DOUBLE, Type.DOUBLE);
2291:                stack.push(top);
2292:            }
2293:
2294:            public void visit_l2i(final Instruction inst) {
2295:                final Expr expr = stack.pop(Type.LONG);
2296:                final Expr top = new CastExpr(expr, Type.INTEGER, Type.INTEGER);
2297:                stack.push(top);
2298:            }
2299:
2300:            public void visit_l2f(final Instruction inst) {
2301:                final Expr expr = stack.pop(Type.LONG);
2302:                final Expr top = new CastExpr(expr, Type.FLOAT, Type.FLOAT);
2303:                stack.push(top);
2304:            }
2305:
2306:            public void visit_l2d(final Instruction inst) {
2307:                final Expr expr = stack.pop(Type.LONG);
2308:                final Expr top = new CastExpr(expr, Type.DOUBLE, Type.DOUBLE);
2309:                stack.push(top);
2310:            }
2311:
2312:            public void visit_f2i(final Instruction inst) {
2313:                final Expr expr = stack.pop(Type.FLOAT);
2314:                final Expr top = new CastExpr(expr, Type.INTEGER, Type.INTEGER);
2315:                stack.push(top);
2316:            }
2317:
2318:            public void visit_f2l(final Instruction inst) {
2319:                final Expr expr = stack.pop(Type.FLOAT);
2320:                final Expr top = new CastExpr(expr, Type.LONG, Type.LONG);
2321:                stack.push(top);
2322:            }
2323:
2324:            public void visit_f2d(final Instruction inst) {
2325:                final Expr expr = stack.pop(Type.FLOAT);
2326:                final Expr top = new CastExpr(expr, Type.DOUBLE, Type.DOUBLE);
2327:                stack.push(top);
2328:            }
2329:
2330:            public void visit_d2i(final Instruction inst) {
2331:                final Expr expr = stack.pop(Type.DOUBLE);
2332:                final Expr top = new CastExpr(expr, Type.INTEGER, Type.INTEGER);
2333:                stack.push(top);
2334:            }
2335:
2336:            public void visit_d2l(final Instruction inst) {
2337:                final Expr expr = stack.pop(Type.DOUBLE);
2338:                final Expr top = new CastExpr(expr, Type.LONG, Type.LONG);
2339:                stack.push(top);
2340:            }
2341:
2342:            public void visit_d2f(final Instruction inst) {
2343:                final Expr expr = stack.pop(Type.DOUBLE);
2344:                final Expr top = new CastExpr(expr, Type.FLOAT, Type.FLOAT);
2345:                stack.push(top);
2346:            }
2347:
2348:            public void visit_i2b(final Instruction inst) {
2349:                final Expr expr = stack.pop(Type.INTEGER);
2350:                final Expr top = new CastExpr(expr, Type.BYTE, Type.INTEGER);
2351:                stack.push(top);
2352:            }
2353:
2354:            public void visit_i2c(final Instruction inst) {
2355:                final Expr expr = stack.pop(Type.INTEGER);
2356:                final Expr top = new CastExpr(expr, Type.CHARACTER,
2357:                        Type.INTEGER);
2358:                stack.push(top);
2359:            }
2360:
2361:            public void visit_i2s(final Instruction inst) {
2362:                final Expr expr = stack.pop(Type.INTEGER);
2363:                final Expr top = new CastExpr(expr, Type.SHORT, Type.INTEGER);
2364:                stack.push(top);
2365:            }
2366:
2367:            /**
2368:             * All <tt>visit_<i>x</i>cmp</tt> push an ArithExpr onto the stack.
2369:             * 
2370:             * @see ArithExpr
2371:             */
2372:            public void visit_lcmp(final Instruction inst) {
2373:                final Expr right = stack.pop(Type.LONG);
2374:                final Expr left = stack.pop(Type.LONG);
2375:                final Expr top = new ArithExpr(ArithExpr.CMP, left, right,
2376:                        Type.INTEGER);
2377:                stack.push(top);
2378:            }
2379:
2380:            public void visit_fcmpl(final Instruction inst) {
2381:                final Expr right = stack.pop(Type.FLOAT);
2382:                final Expr left = stack.pop(Type.FLOAT);
2383:                final Expr top = new ArithExpr(ArithExpr.CMPL, left, right,
2384:                        Type.INTEGER);
2385:                stack.push(top);
2386:            }
2387:
2388:            public void visit_fcmpg(final Instruction inst) {
2389:                final Expr right = stack.pop(Type.FLOAT);
2390:                final Expr left = stack.pop(Type.FLOAT);
2391:                final Expr top = new ArithExpr(ArithExpr.CMPG, left, right,
2392:                        Type.INTEGER);
2393:                stack.push(top);
2394:            }
2395:
2396:            public void visit_dcmpl(final Instruction inst) {
2397:                final Expr right = stack.pop(Type.DOUBLE);
2398:                final Expr left = stack.pop(Type.DOUBLE);
2399:                final Expr top = new ArithExpr(ArithExpr.CMPL, left, right,
2400:                        Type.INTEGER);
2401:                stack.push(top);
2402:            }
2403:
2404:            public void visit_dcmpg(final Instruction inst) {
2405:                final Expr right = stack.pop(Type.DOUBLE);
2406:                final Expr left = stack.pop(Type.DOUBLE);
2407:                final Expr top = new ArithExpr(ArithExpr.CMPG, left, right,
2408:                        Type.INTEGER);
2409:                stack.push(top);
2410:            }
2411:
2412:            /**
2413:             * All <tt>visit_<i>x</i>eg</tt> add an IfZeroStmt to the statement
2414:             * list.
2415:             * 
2416:             * @see IfZeroStmt
2417:             */
2418:            public void visit_ifeq(final Instruction inst) {
2419:                // It isn't necessary to saveStack since removing critical edges
2420:                // guarantees that no code will be inserted before the branch
2421:                // since there cannot be more than one predecessor of either of
2422:                // the successor nodes (and hence no phi statements, even in SSAPRE).
2423:                // saveStack();
2424:
2425:                final Expr left = stack.pop(Type.INTEGER);
2426:                final Block t = (Block) block.graph().getNode(inst.operand());
2427:                Assert.isTrue(t != null, "No block for " + inst);
2428:
2429:                addStmt(new IfZeroStmt(IfStmt.EQ, left, t, next));
2430:            }
2431:
2432:            public void visit_ifne(final Instruction inst) {
2433:                // It isn't necessary to saveStack since removing critical edges
2434:                // guarantees that no code will be inserted before the branch
2435:                // since there cannot be more than one predecessor of either of
2436:                // the successor nodes (and hence no phi statements, even in SSAPRE).
2437:                // saveStack();
2438:
2439:                final Expr left = stack.pop(Type.INTEGER);
2440:                final Block t = (Block) block.graph().getNode(inst.operand());
2441:                Assert.isTrue(t != null, "No block for " + inst);
2442:
2443:                addStmt(new IfZeroStmt(IfStmt.NE, left, t, next));
2444:            }
2445:
2446:            public void visit_iflt(final Instruction inst) {
2447:                // It isn't necessary to saveStack since removing critical edges
2448:                // guarantees that no code will be inserted before the branch
2449:                // since there cannot be more than one predecessor of either of
2450:                // the successor nodes (and hence no phi statements, even in SSAPRE).
2451:                // saveStack();
2452:
2453:                final Expr left = stack.pop(Type.INTEGER);
2454:                final Block t = (Block) block.graph().getNode(inst.operand());
2455:                Assert.isTrue(t != null, "No block for " + inst);
2456:
2457:                addStmt(new IfZeroStmt(IfStmt.LT, left, t, next));
2458:            }
2459:
2460:            public void visit_ifge(final Instruction inst) {
2461:                // It isn't necessary to saveStack since removing critical edges
2462:                // guarantees that no code will be inserted before the branch
2463:                // since there cannot be more than one predecessor of either of
2464:                // the successor nodes (and hence no phi statements, even in SSAPRE).
2465:                // saveStack();
2466:
2467:                final Expr left = stack.pop(Type.INTEGER);
2468:                final Block t = (Block) block.graph().getNode(inst.operand());
2469:                Assert.isTrue(t != null, "No block for " + inst);
2470:
2471:                addStmt(new IfZeroStmt(IfStmt.GE, left, t, next));
2472:            }
2473:
2474:            public void visit_ifgt(final Instruction inst) {
2475:                // It isn't necessary to saveStack since removing critical edges
2476:                // guarantees that no code will be inserted before the branch
2477:                // since there cannot be more than one predecessor of either of
2478:                // the successor nodes (and hence no phi statements, even in SSAPRE).
2479:                // saveStack();
2480:
2481:                final Expr left = stack.pop(Type.INTEGER);
2482:                final Block t = (Block) block.graph().getNode(inst.operand());
2483:                Assert.isTrue(t != null, "No block for " + inst);
2484:
2485:                addStmt(new IfZeroStmt(IfStmt.GT, left, t, next));
2486:            }
2487:
2488:            public void visit_ifle(final Instruction inst) {
2489:                // It isn't necessary to saveStack since removing critical edges
2490:                // guarantees that no code will be inserted before the branch
2491:                // since there cannot be more than one predecessor of either of
2492:                // the successor nodes (and hence no phi statements, even in SSAPRE).
2493:                // saveStack();
2494:
2495:                final Expr left = stack.pop(Type.INTEGER);
2496:                final Block t = (Block) block.graph().getNode(inst.operand());
2497:                Assert.isTrue(t != null, "No block for " + inst);
2498:
2499:                addStmt(new IfZeroStmt(IfStmt.LE, left, t, next));
2500:            }
2501:
2502:            /**
2503:             * All <tt>visit_if_<i>x</i>cmp<i>y</i></tt> add a IfCmpStmt to the
2504:             * statement list.
2505:             */
2506:            public void visit_if_icmpeq(final Instruction inst) {
2507:                // It isn't necessary to saveStack since removing critical edges
2508:                // guarantees that no code will be inserted before the branch
2509:                // since there cannot be more than one predecessor of either of
2510:                // the successor nodes (and hence no phi statements, even in SSAPRE).
2511:                // saveStack();
2512:
2513:                final Expr right = stack.pop(Type.INTEGER);
2514:                final Expr left = stack.pop(Type.INTEGER);
2515:                final Block t = (Block) block.graph().getNode(inst.operand());
2516:                Assert.isTrue(t != null, "No block for " + inst);
2517:
2518:                addStmt(new IfCmpStmt(IfStmt.EQ, left, right, t, next));
2519:            }
2520:
2521:            public void visit_if_icmpne(final Instruction inst) {
2522:                // It isn't necessary to saveStack since removing critical edges
2523:                // guarantees that no code will be inserted before the branch
2524:                // since there cannot be more than one predecessor of either of
2525:                // the successor nodes (and hence no phi statements, even in SSAPRE).
2526:                // saveStack();
2527:
2528:                final Expr right = stack.pop(Type.INTEGER);
2529:                final Expr left = stack.pop(Type.INTEGER);
2530:                final Block t = (Block) block.graph().getNode(inst.operand());
2531:                Assert.isTrue(t != null, "No block for " + inst);
2532:
2533:                addStmt(new IfCmpStmt(IfStmt.NE, left, right, t, next));
2534:            }
2535:
2536:            public void visit_if_icmplt(final Instruction inst) {
2537:                // It isn't necessary to saveStack since removing critical edges
2538:                // guarantees that no code will be inserted before the branch
2539:                // since there cannot be more than one predecessor of either of
2540:                // the successor nodes (and hence no phi statements, even in SSAPRE).
2541:                // saveStack();
2542:
2543:                final Expr right = stack.pop(Type.INTEGER);
2544:                final Expr left = stack.pop(Type.INTEGER);
2545:                final Block t = (Block) block.graph().getNode(inst.operand());
2546:                Assert.isTrue(t != null, "No block for " + inst);
2547:
2548:                addStmt(new IfCmpStmt(IfStmt.LT, left, right, t, next));
2549:            }
2550:
2551:            public void visit_if_icmpge(final Instruction inst) {
2552:                // It isn't necessary to saveStack since removing critical edges
2553:                // guarantees that no code will be inserted before the branch
2554:                // since there cannot be more than one predecessor of either of
2555:                // the successor nodes (and hence no phi statements, even in SSAPRE).
2556:                // saveStack();
2557:
2558:                final Expr right = stack.pop(Type.INTEGER);
2559:                final Expr left = stack.pop(Type.INTEGER);
2560:                final Block t = (Block) block.graph().getNode(inst.operand());
2561:                Assert.isTrue(t != null, "No block for " + inst);
2562:
2563:                addStmt(new IfCmpStmt(IfStmt.GE, left, right, t, next));
2564:            }
2565:
2566:            public void visit_if_icmpgt(final Instruction inst) {
2567:                // It isn't necessary to saveStack since removing critical edges
2568:                // guarantees that no code will be inserted before the branch
2569:                // since there cannot be more than one predecessor of either of
2570:                // the successor nodes (and hence no phi statements, even in SSAPRE).
2571:                // saveStack();
2572:
2573:                final Expr right = stack.pop(Type.INTEGER);
2574:                final Expr left = stack.pop(Type.INTEGER);
2575:                final Block t = (Block) block.graph().getNode(inst.operand());
2576:                Assert.isTrue(t != null, "No block for " + inst);
2577:
2578:                addStmt(new IfCmpStmt(IfStmt.GT, left, right, t, next));
2579:            }
2580:
2581:            public void visit_if_icmple(final Instruction inst) {
2582:                // It isn't necessary to saveStack since removing critical edges
2583:                // guarantees that no code will be inserted before the branch
2584:                // since there cannot be more than one predecessor of either of
2585:                // the successor nodes (and hence no phi statements, even in SSAPRE).
2586:                // saveStack();
2587:
2588:                final Expr right = stack.pop(Type.INTEGER);
2589:                final Expr left = stack.pop(Type.INTEGER);
2590:                final Block t = (Block) block.graph().getNode(inst.operand());
2591:                Assert.isTrue(t != null, "No block for " + inst);
2592:
2593:                addStmt(new IfCmpStmt(IfStmt.LE, left, right, t, next));
2594:            }
2595:
2596:            public void visit_if_acmpeq(final Instruction inst) {
2597:                // It isn't necessary to saveStack since removing critical edges
2598:                // guarantees that no code will be inserted before the branch
2599:                // since there cannot be more than one predecessor of either of
2600:                // the successor nodes (and hence no phi statements, even in SSAPRE).
2601:                // saveStack();
2602:
2603:                final Expr right = stack.pop(Type.OBJECT);
2604:                final Expr left = stack.pop(Type.OBJECT);
2605:                final Block t = (Block) block.graph().getNode(inst.operand());
2606:                Assert.isTrue(t != null, "No block for " + inst);
2607:
2608:                addStmt(new IfCmpStmt(IfStmt.EQ, left, right, t, next));
2609:            }
2610:
2611:            public void visit_if_acmpne(final Instruction inst) {
2612:                // It isn't necessary to saveStack since removing critical edges
2613:                // guarantees that no code will be inserted before the branch
2614:                // since there cannot be more than one predecessor of either of
2615:                // the successor nodes (and hence no phi statements, even in SSAPRE).
2616:                // saveStack();
2617:
2618:                final Expr right = stack.pop(Type.OBJECT);
2619:                final Expr left = stack.pop(Type.OBJECT);
2620:                final Block t = (Block) block.graph().getNode(inst.operand());
2621:                Assert.isTrue(t != null, "No block for " + inst);
2622:
2623:                addStmt(new IfCmpStmt(IfStmt.NE, left, right, t, next));
2624:            }
2625:
2626:            /**
2627:             * Adds a GotoStmt to the statement list.
2628:             * 
2629:             * @see GotoStmt
2630:             */
2631:            public void visit_goto(final Instruction inst) {
2632:                final Block t = (Block) block.graph().getNode(inst.operand());
2633:                Assert.isTrue(t != null, "No block for " + inst);
2634:                addStmt(new GotoStmt(t));
2635:            }
2636:
2637:            /**
2638:             * Adds a JsrStmt to the statement list.
2639:             * 
2640:             * @see JsrStmt
2641:             */
2642:            public void visit_jsr(final Instruction inst) {
2643:                // Push the return address after we add the statement.
2644:                // This prevents it from being saved to a local variable.
2645:                // It's illegal to load a return address from a local variable,
2646:                // so we can't save it.
2647:                final Subroutine sub = block.graph().labelSub(
2648:                        (Label) inst.operand());
2649:                addStmt(new JsrStmt(sub, next));
2650:                stack.push(new ReturnAddressExpr(Type.ADDRESS));
2651:            }
2652:
2653:            /**
2654:             * Adds a RetStmt to the statement list.
2655:             * 
2656:             * @see RetStmt
2657:             */
2658:            public void visit_ret(final Instruction inst) {
2659:                Assert.isTrue(sub != null);
2660:                addStmt(new RetStmt(sub));
2661:            }
2662:
2663:            /**
2664:             * Add a SwitchStmt to the statement list.
2665:             * 
2666:             * @see SwitchStmt
2667:             */
2668:            public void visit_switch(final Instruction inst) {
2669:                // It isn't necessary to saveStack since removing critical edges
2670:                // guarantees that no code will be inserted before the branch
2671:                // since there cannot be more than one predecessor of either of
2672:                // the successor nodes (and hence no phi statements, even in SSAPRE).
2673:                // saveStack();
2674:
2675:                final Expr index = stack.pop(Type.INTEGER);
2676:
2677:                final Switch sw = (Switch) inst.operand();
2678:
2679:                final Block defaultTarget = (Block) block.graph().getNode(
2680:                        sw.defaultTarget());
2681:                Assert.isTrue(defaultTarget != null, "No block for " + inst);
2682:
2683:                final Block[] targets = new Block[sw.targets().length];
2684:
2685:                for (int i = 0; i < targets.length; i++) {
2686:                    targets[i] = (Block) block.graph().getNode(sw.targets()[i]);
2687:                    Assert.isTrue(targets[i] != null, "No block for " + inst);
2688:                }
2689:
2690:                addStmt(new SwitchStmt(index, defaultTarget, targets, sw
2691:                        .values()));
2692:            }
2693:
2694:            /**
2695:             * All <tt>visit_<i>x</i>return</tt> add a ReturnExprStmt to the
2696:             * statement list.
2697:             * 
2698:             * @see ReturnExprStmt
2699:             */
2700:            public void visit_ireturn(final Instruction inst) {
2701:                final Expr expr = stack.pop(Type.INTEGER);
2702:                addStmt(new ReturnExprStmt(expr));
2703:            }
2704:
2705:            public void visit_lreturn(final Instruction inst) {
2706:                final Expr expr = stack.pop(Type.LONG);
2707:                addStmt(new ReturnExprStmt(expr));
2708:            }
2709:
2710:            public void visit_freturn(final Instruction inst) {
2711:                final Expr expr = stack.pop(Type.FLOAT);
2712:                addStmt(new ReturnExprStmt(expr));
2713:            }
2714:
2715:            public void visit_dreturn(final Instruction inst) {
2716:                final Expr expr = stack.pop(Type.DOUBLE);
2717:                addStmt(new ReturnExprStmt(expr));
2718:            }
2719:
2720:            public void visit_areturn(final Instruction inst) {
2721:                final Expr expr = stack.pop(Type.OBJECT);
2722:                addStmt(new ReturnExprStmt(expr));
2723:            }
2724:
2725:            /**
2726:             * Adds a ReturnStmt to the statement list.
2727:             */
2728:            public void visit_return(final Instruction inst) {
2729:                addStmt(new ReturnStmt());
2730:            }
2731:
2732:            /**
2733:             * Pushes a StaticFieldExpr onto the operand stack.
2734:             */
2735:            public void visit_getstatic(final Instruction inst) {
2736:                final MemberRef field = (MemberRef) inst.operand();
2737:                final Type type = field.nameAndType().type();
2738:
2739:                try {
2740:                    final EditorContext context = block.graph().method()
2741:                            .declaringClass().context();
2742:                    final FieldEditor e = context.editField(field);
2743:
2744:                    if (e.isFinal()) {
2745:                        if (e.constantValue() != null) {
2746:                            final Expr top = new ConstantExpr(
2747:                                    e.constantValue(), type);
2748:                            stack.push(top);
2749:                            context.release(e.fieldInfo());
2750:                            return;
2751:                        }
2752:                    }
2753:
2754:                    context.release(e.fieldInfo());
2755:                } catch (final NoSuchFieldException e) {
2756:                    // No field found. Silently assume non-final.
2757:                }
2758:
2759:                final Expr top = new StaticFieldExpr(field, type);
2760:                stack.push(top);
2761:            }
2762:
2763:            public void visit_putstatic(final Instruction inst) {
2764:                final MemberRef field = (MemberRef) inst.operand();
2765:                final Type type = field.nameAndType().type();
2766:                final Expr value = stack.pop(type);
2767:                final StaticFieldExpr target = new StaticFieldExpr(field, type);
2768:                addStore(target, value);
2769:            }
2770:
2771:            public void visit_putstatic_nowb(final Instruction inst) {
2772:                visit_putstatic(inst);
2773:            }
2774:
2775:            /**
2776:             * Pushes a FieldExpr onto the operand stack.
2777:             */
2778:            public void visit_getfield(final Instruction inst) {
2779:                final MemberRef field = (MemberRef) inst.operand();
2780:                final Type type = field.nameAndType().type();
2781:                final Expr obj = stack.pop(Type.OBJECT);
2782:                final Expr check = new ZeroCheckExpr(obj, obj.type());
2783:                final Expr top = new FieldExpr(check, field, type);
2784:                stack.push(top);
2785:            }
2786:
2787:            public void visit_putfield(final Instruction inst) {
2788:                final MemberRef field = (MemberRef) inst.operand();
2789:                final Type type = field.nameAndType().type();
2790:                final Expr value = stack.pop(type);
2791:                final Expr obj = stack.pop(Type.OBJECT);
2792:                Expr ucCheck = obj;
2793:
2794:                if (Tree.USE_PERSISTENT) {
2795:                    ucCheck = new UCExpr(obj, UCExpr.POINTER, obj.type());
2796:                }
2797:
2798:                final Expr check = new ZeroCheckExpr(ucCheck, obj.type());
2799:                final FieldExpr target = new FieldExpr(check, field, type);
2800:                addStore(target, value);
2801:            }
2802:
2803:            // Don't insert UCExpr
2804:            public void visit_putfield_nowb(final Instruction inst) {
2805:                final MemberRef field = (MemberRef) inst.operand();
2806:                final Type type = field.nameAndType().type();
2807:                final Expr value = stack.pop(type);
2808:                final Expr obj = stack.pop(Type.OBJECT);
2809:                final Expr check = new ZeroCheckExpr(obj, obj.type());
2810:                final FieldExpr target = new FieldExpr(check, field, type);
2811:                addStore(target, value);
2812:            }
2813:
2814:            /**
2815:             * All <tt>visit_invoke<i>x</i></tt> deal with a CallMethodExpr or a
2816:             * CallStaticExpr.
2817:             * 
2818:             * @see CallMethodExpr
2819:             * @see CallStaticExpr
2820:             */
2821:            public void visit_invokevirtual(final Instruction inst) {
2822:                addCall(inst, CallMethodExpr.VIRTUAL);
2823:            }
2824:
2825:            public void visit_invokespecial(final Instruction inst) {
2826:                addCall(inst, CallMethodExpr.NONVIRTUAL);
2827:            }
2828:
2829:            public void visit_invokestatic(final Instruction inst) {
2830:                addCall(inst, 0);
2831:            }
2832:
2833:            public void visit_invokeinterface(final Instruction inst) {
2834:                addCall(inst, CallMethodExpr.INTERFACE);
2835:            }
2836:
2837:            /**
2838:             * Creates either a CallMethodExpr or a CallStaticExpr to represent a method
2839:             * call. After obtaining some information about the method. The parameters
2840:             * to the methods are popped from the operand stack. If the method is not
2841:             * static, the "this" object is popped from the operand stack. A
2842:             * CallMethodExpr is created for a non-static method and a CallStaticExpr is
2843:             * created for a static method. If the method returns a value, the Call*Expr
2844:             * is pushed onto the stack. If the method has no return value, it is
2845:             * wrapped in an ExprStmt and is added to the statement list.
2846:             */
2847:            private void addCall(final Instruction inst, final int kind) {
2848:                final MemberRef method = (MemberRef) inst.operand();
2849:                final Type type = method.nameAndType().type();
2850:
2851:                final Type[] paramTypes = type.paramTypes();
2852:                final Expr[] params = new Expr[paramTypes.length];
2853:
2854:                for (int i = paramTypes.length - 1; i >= 0; i--) {
2855:                    params[i] = stack.pop(paramTypes[i]);
2856:                }
2857:
2858:                Expr top;
2859:
2860:                if (inst.opcodeClass() != Opcode.opcx_invokestatic) {
2861:                    final Expr obj = stack.pop(Type.OBJECT);
2862:
2863:                    top = new CallMethodExpr(kind, obj, params, method, type
2864:                            .returnType());
2865:
2866:                } else {
2867:                    top = new CallStaticExpr(params, method, type.returnType());
2868:                }
2869:
2870:                if (type.returnType().equals(Type.VOID)) {
2871:                    addStmt(new ExprStmt(top));
2872:
2873:                } else {
2874:                    stack.push(top);
2875:                }
2876:            }
2877:
2878:            /**
2879:             * Pushes a NewExpr onto the operand stack.
2880:             * 
2881:             * @see NewExpr
2882:             */
2883:            public void visit_new(final Instruction inst) {
2884:                final Type type = (Type) inst.operand();
2885:                final Expr top = new NewExpr(type, Type.OBJECT);
2886:                stack.push(top);
2887:
2888:                db("      new: " + top);
2889:            }
2890:
2891:            /**
2892:             * Pushes a NewArrayExpr onto the operand stack.
2893:             */
2894:            public void visit_newarray(final Instruction inst) {
2895:                final Type type = (Type) inst.operand();
2896:                final Expr size = stack.pop(Type.INTEGER);
2897:                final Expr top = new NewArrayExpr(size, type, type.arrayType());
2898:                stack.push(top);
2899:            }
2900:
2901:            /**
2902:             * Pushes an ArrayLengthExpr onto the operand stack.
2903:             * 
2904:             * @see ArrayLengthExpr
2905:             */
2906:            public void visit_arraylength(final Instruction inst) {
2907:                final Expr array = stack.pop(Type.OBJECT);
2908:                final Expr top = new ArrayLengthExpr(array, Type.INTEGER);
2909:                stack.push(top);
2910:            }
2911:
2912:            /**
2913:             * Adds a ThrowStmt to the statement list.
2914:             * 
2915:             * @see ThrowStmt
2916:             */
2917:            public void visit_athrow(final Instruction inst) {
2918:                final Expr expr = stack.pop(Type.THROWABLE);
2919:                addStmt(new ThrowStmt(expr));
2920:            }
2921:
2922:            /**
2923:             * Pushes a CastExpr onto the operand stack.
2924:             * 
2925:             * @see CastExpr
2926:             */
2927:            public void visit_checkcast(final Instruction inst) {
2928:                final Expr expr = stack.pop(Type.OBJECT);
2929:                final Type type = (Type) inst.operand();
2930:                final Expr top = new CastExpr(expr, type, type);
2931:                stack.push(top);
2932:            }
2933:
2934:            /**
2935:             * Pushes an InstanceOfExpr onto the operand stack.
2936:             * 
2937:             * @see InstanceOfExpr
2938:             */
2939:            public void visit_instanceof (final Instruction inst) {
2940:                final Type type = (Type) inst.operand();
2941:                final Expr expr = stack.pop(Type.OBJECT);
2942:                final Expr top = new InstanceOfExpr(expr, type, Type.INTEGER);
2943:                stack.push(top);
2944:            }
2945:
2946:            /**
2947:             * Both <tt>monitor</tt> visitors add a MonitorStmt to the statement list.
2948:             * 
2949:             * @see MonitorStmt
2950:             */
2951:            public void visit_monitorenter(final Instruction inst) {
2952:                final Expr obj = stack.pop(Type.OBJECT);
2953:                addStmt(new MonitorStmt(MonitorStmt.ENTER, obj));
2954:            }
2955:
2956:            public void visit_monitorexit(final Instruction inst) {
2957:                final Expr obj = stack.pop(Type.OBJECT);
2958:                addStmt(new MonitorStmt(MonitorStmt.EXIT, obj));
2959:            }
2960:
2961:            /**
2962:             * Push a NewMultiArrayExpr onto the operand stack.
2963:             * 
2964:             * @see NewMultiArrayExpr
2965:             */
2966:            public void visit_multianewarray(final Instruction inst) {
2967:                final MultiArrayOperand operand = (MultiArrayOperand) inst
2968:                        .operand();
2969:
2970:                final Expr[] dim = new Expr[operand.dimensions()];
2971:
2972:                for (int i = dim.length - 1; i >= 0; i--) {
2973:                    dim[i] = stack.pop(Type.INTEGER);
2974:                }
2975:
2976:                final Type type = operand.type();
2977:
2978:                final Expr top = new NewMultiArrayExpr(dim, type
2979:                        .elementType(dim.length), type);
2980:
2981:                stack.push(top);
2982:            }
2983:
2984:            /**
2985:             * Both <tt>visit_<i>x</i>null</tt> add an IfZeroStmt to the statement
2986:             * list.
2987:             * 
2988:             * ssee IfZeroStmt
2989:             */
2990:            public void visit_ifnull(final Instruction inst) {
2991:                // It isn't necessary to saveStack since removing critical edges
2992:                // guarantees that no code will be inserted before the branch
2993:                // since there cannot be more than one predecessor of either of
2994:                // the successor nodes (and hence no phi statements, even in SSAPRE).
2995:                // saveStack();
2996:
2997:                final Expr left = stack.pop(Type.OBJECT);
2998:                final Block t = (Block) block.graph().getNode(inst.operand());
2999:                Assert.isTrue(t != null, "No block for " + inst);
3000:
3001:                addStmt(new IfZeroStmt(IfStmt.EQ, left, t, next));
3002:            }
3003:
3004:            public void visit_ifnonnull(final Instruction inst) {
3005:                // It isn't necessary to saveStack since removing critical edges
3006:                // guarantees that no code will be inserted before the branch
3007:                // since there cannot be more than one predecessor of either of
3008:                // the successor nodes (and hence no phi statements, even in SSAPRE).
3009:                // saveStack();
3010:
3011:                final Expr left = stack.pop(Type.OBJECT);
3012:                final Block t = (Block) block.graph().getNode(inst.operand());
3013:                Assert.isTrue(t != null, "No block for " + inst);
3014:
3015:                addStmt(new IfZeroStmt(IfStmt.NE, left, t, next));
3016:            }
3017:
3018:            /**
3019:             * Replaces the expression on the top of the stack with an RCExpr.
3020:             * 
3021:             * @see RCExpr
3022:             */
3023:            public void visit_rc(final Instruction inst) {
3024:                final Integer depth = (Integer) inst.operand();
3025:                final Expr object = stack.peek(depth.intValue());
3026:                stack.replace(depth.intValue(), new RCExpr(object, object
3027:                        .type()));
3028:            }
3029:
3030:            /**
3031:             * 
3032:             */
3033:            public void visit_aupdate(final Instruction inst) {
3034:                Integer depth = (Integer) inst.operand();
3035:
3036:                if (Tree.AUPDATE_FIX_HACK) {
3037:                    // Hack to fix a bug in old bloat-generated code:
3038:
3039:                    if (depth.intValue() == 1) {
3040:                        final Expr object = stack.peek();
3041:
3042:                        if (object.type().isWide()) {
3043:                            depth = new Integer(2);
3044:                            inst.setOperand(depth);
3045:                            Tree.AUPDATE_FIX_HACK_CHANGED = true;
3046:                        }
3047:                    }
3048:                }
3049:
3050:                final Expr object = stack.peek(depth.intValue());
3051:                stack.replace(depth.intValue(), new UCExpr(object,
3052:                        UCExpr.POINTER, object.type()));
3053:            }
3054:
3055:            /**
3056:             * Replace the expression at the stack depth specified in the instruction
3057:             * with a UCExpr.
3058:             * 
3059:             * @see UCExpr
3060:             */
3061:            public void visit_supdate(final Instruction inst) {
3062:                final Integer depth = (Integer) inst.operand();
3063:                final Expr object = stack.peek(depth.intValue());
3064:                stack.replace(depth.intValue(), new UCExpr(object,
3065:                        UCExpr.SCALAR, object.type()));
3066:            }
3067:
3068:            /**
3069:             * Add a SCStmt to the statement list
3070:             * 
3071:             * @see SCStmt
3072:             */
3073:            public void visit_aswizzle(final Instruction inst) {
3074:                final Expr index = stack.pop(Type.INTEGER);
3075:                final Expr array = stack.pop(Type.OBJECT.arrayType());
3076:
3077:                addStmt(new SCStmt(array, index));
3078:
3079:            }
3080:
3081:            /**
3082:             * Add a SRStmt to the statement list.
3083:             * 
3084:             * @see SRStmt
3085:             */
3086:            public void visit_aswrange(final Instruction inst) {
3087:                final Expr end = stack.pop(Type.INTEGER);
3088:                final Expr start = stack.pop(Type.INTEGER);
3089:                final Expr array = stack.pop(Type.OBJECT.arrayType());
3090:
3091:                addStmt(new SRStmt(array, start, end));
3092:            }
3093:
3094:            /**
3095:             * Visit all the statements in the statement list.
3096:             */
3097:            public void visitForceChildren(final TreeVisitor visitor) {
3098:                final LinkedList list = new LinkedList(stmts);
3099:
3100:                if (visitor.reverse()) {
3101:                    final ListIterator iter = list.listIterator(stmts.size());
3102:
3103:                    while (iter.hasPrevious()) {
3104:                        final Stmt s = (Stmt) iter.previous();
3105:                        s.visit(visitor);
3106:                    }
3107:                } else {
3108:                    final ListIterator iter = list.listIterator();
3109:
3110:                    while (iter.hasNext()) {
3111:                        final Stmt s = (Stmt) iter.next();
3112:                        s.visit(visitor);
3113:                    }
3114:                }
3115:            }
3116:
3117:            public void visit(final TreeVisitor visitor) {
3118:                visitor.visitTree(this );
3119:            }
3120:
3121:            public Node parent() {
3122:                return null;
3123:            }
3124:
3125:            public Block block() {
3126:                return block;
3127:            }
3128:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.