Source Code Cross Referenced for CodeGenerator.java in  » Database-DBMS » db4o-6.4 » EDU » purdue » cs » bloat » codegen » 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.codegen 
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.codegen;
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.tree.*;
0028:        import EDU.purdue.cs.bloat.util.*;
0029:
0030:        /**
0031:         * CodeGenerator performs some final optimizations and is used (via a visitor)
0032:         * to generate bytecode for the contents of a control flow graph.
0033:         * 
0034:         * @see FlowGraph
0035:         */
0036:        public class CodeGenerator extends TreeVisitor implements  Opcode {
0037:            public static boolean DEBUG = false;
0038:
0039:            public static boolean USE_PERSISTENT = false; // Generate _nowb
0040:
0041:            /**
0042:             * Use information about placement of local variables to eliminate loads and
0043:             * stores in favor of stack manipulations
0044:             */
0045:            public static boolean OPT_STACK = false;
0046:
0047:            public static boolean DB_OPT_STACK = false;
0048:
0049:            protected MethodEditor method;
0050:
0051:            protected Set visited;
0052:
0053:            protected Map postponedInstructions;
0054:
0055:            protected Block next;
0056:
0057:            protected int stackHeight; // The current height of the stack
0058:
0059:            StackOptimizer currentSO; // object used to determine where to apply
0060:
0061:            // stack optimization
0062:
0063:            /**
0064:             * Constructor.
0065:             * 
0066:             * @param method
0067:             *            The method for which bytecode is generated.
0068:             */
0069:            public CodeGenerator(final MethodEditor method) {
0070:                this .method = method;
0071:                this .postponedInstructions = new HashMap();
0072:            }
0073:
0074:            /**
0075:             * Visits the nodes in the method's control flow graph and ensures that
0076:             * information about the method's basic blocks is consistent and correct.
0077:             * 
0078:             * @param cfg
0079:             *            The control flow graph associated with this method.
0080:             */
0081:            public void visitFlowGraph(final FlowGraph cfg) {
0082:                // Generate the code.
0083:
0084:                visited = new HashSet();
0085:                visited.add(cfg.source());
0086:                visited.add(cfg.sink());
0087:
0088:                final Iterator e = cfg.trace().iterator();
0089:
0090:                Assert.isTrue(e.hasNext(), "trace is empty");
0091:
0092:                stackHeight = 0; // At beginning of method stack has height 0
0093:
0094:                Block block = (Block) e.next();
0095:
0096:                // Visit each block in the method (via the trace in the method's CFG)
0097:                // and ensure that the first (and ONLY the first) label in the code
0098:                // is marked as starting a block.
0099:                while (block != null) {
0100:                    if (e.hasNext()) {
0101:                        next = (Block) e.next();
0102:
0103:                    } else {
0104:                        next = null;
0105:                    }
0106:
0107:                    if (CodeGenerator.DEBUG) {
0108:                        System.out.println("code for " + block);
0109:                    }
0110:
0111:                    // Make sure the first label is marked as starting a block
0112:                    // and the rest are marked as not starting a block.
0113:                    block.visit(new TreeVisitor() {
0114:                        boolean startsBlock = true;
0115:
0116:                        public void visitLabelStmt(final LabelStmt stmt) {
0117:                            stmt.label().setStartsBlock(startsBlock);
0118:                            startsBlock = false;
0119:                        }
0120:
0121:                        public void visitStmt(final Stmt stmt) {
0122:                        }
0123:                    });
0124:
0125:                    // Generate the code for each block
0126:                    visited.add(block);
0127:                    // currentSO is the StackOptimizer object that discerns
0128:                    // where dups may be used instead of loads
0129:                    if (CodeGenerator.OPT_STACK) {
0130:                        currentSO = block.stackOptimizer();
0131:                    }
0132:                    block.visitChildren(this );
0133:
0134:                    block = next;
0135:                }
0136:
0137:                Assert.isTrue(visited.size() == cfg.size(),
0138:                        "did not visit all blocks while generating code");
0139:
0140:                next = null;
0141:                visited = null;
0142:
0143:                // Go through the catch blocks and determine the what the
0144:                // protected regions are that correspond to the catch blocks.
0145:                // Create TryCatch objects to represent the protected regions.
0146:
0147:                final Iterator iter = cfg.catchBlocks().iterator();
0148:
0149:                while (iter.hasNext()) {
0150:                    final Block catchBlock = (Block) iter.next();
0151:                    final Handler handler = (Handler) cfg.handlersMap().get(
0152:                            catchBlock);
0153:
0154:                    Type type = handler.catchType();
0155:
0156:                    if (type.isNull()) {
0157:                        type = null;
0158:                    }
0159:
0160:                    // First block in protected block
0161:                    Block begin = null;
0162:
0163:                    final Iterator blocks = cfg.trace().iterator();
0164:
0165:                    while (blocks.hasNext()) {
0166:                        block = (Block) blocks.next();
0167:
0168:                        if (handler.protectedBlocks().contains(block)) {
0169:                            if (begin == null) {
0170:                                begin = block;
0171:                            }
0172:
0173:                        } else if (begin != null) {
0174:                            // The block is no longer protected, its the end of the
0175:                            // protected region
0176:                            final TryCatch tc = new TryCatch(begin.label(),
0177:                                    block.label(), catchBlock.label(), type);
0178:                            method.addTryCatch(tc);
0179:
0180:                            begin = null;
0181:                        }
0182:                    }
0183:                }
0184:            }
0185:
0186:            /**
0187:             * Simplifies the control flow of a method by changing jump and return
0188:             * statements into gotos where appropriate.
0189:             */
0190:            public void simplifyControlFlow(final FlowGraph cfg) {
0191:                // Remove any blocks from the CFG that consist of solely jumps
0192:                removeEmptyBlocks(cfg);
0193:
0194:                cfg.visit(new TreeVisitor() {
0195:                    public void visitJsrStmt(final JsrStmt stmt) {
0196:                        final Subroutine sub = stmt.sub();
0197:
0198:                        // If there is only 1 path through the sub, replace both
0199:                        // the jsr and the ret with gotos.
0200:                        if (sub.numPaths() == 1) {
0201:                            final Block exit = sub.exit();
0202:
0203:                            // Remember that it is not required for a subroutine to have
0204:                            // a ret. So, no exit block may be identified and we'll
0205:                            // have to make sure one exists.
0206:                            if (exit != null) {
0207:                                final JumpStmt oldJump = (JumpStmt) exit.tree()
0208:                                        .lastStmt();
0209:                                final JumpStmt jump = new GotoStmt(stmt
0210:                                        .follow());
0211:                                jump.catchTargets().addAll(
0212:                                        oldJump.catchTargets());
0213:                                oldJump.replaceWith(jump);
0214:                            }
0215:
0216:                            final JumpStmt jump = new GotoStmt(sub.entry());
0217:                            jump.catchTargets().addAll(stmt.catchTargets());
0218:                            stmt.replaceWith(jump);
0219:
0220:                            // The subroutine is no longer really a subroutine
0221:                            cfg.removeSub(sub);
0222:
0223:                            // Clean up the CFG by removing all AddressStoreStmts that
0224:                            // store the address of the "removed" subroutine.
0225:                            cfg.visit(new TreeVisitor() {
0226:                                Iterator iter;
0227:
0228:                                public void visitTree(final Tree tree) {
0229:                                    iter = tree.stmts().iterator();
0230:
0231:                                    while (iter.hasNext()) {
0232:                                        final Stmt s = (Stmt) iter.next();
0233:
0234:                                        if (s instanceof  AddressStoreStmt) {
0235:                                            final AddressStoreStmt store = (AddressStoreStmt) s;
0236:
0237:                                            if (store.sub() == sub) {
0238:                                                iter.remove();
0239:                                            }
0240:                                        }
0241:                                    }
0242:                                }
0243:                            });
0244:                        }
0245:                    }
0246:
0247:                    public void visitStmt(final Stmt stmt) {
0248:                    }
0249:                });
0250:            }
0251:
0252:            /**
0253:             * Replace PhiStmts with copies that accomplish what the PhiStmts represent.
0254:             * Then remove the PhiStmts from the control flow graph.
0255:             */
0256:            public void replacePhis(final FlowGraph cfg) {
0257:                replaceCatchPhis(cfg);
0258:                replaceJoinPhis(cfg);
0259:
0260:                // Remove the phis.
0261:                cfg.visit(new TreeVisitor() {
0262:                    public void visitTree(final Tree tree) {
0263:                        final Iterator e = tree.stmts().iterator();
0264:
0265:                        while (e.hasNext()) {
0266:                            final Stmt s = (Stmt) e.next();
0267:
0268:                            if (s instanceof  PhiStmt) {
0269:                                e.remove();
0270:                            }
0271:                        }
0272:                    }
0273:                });
0274:            }
0275:
0276:            /**
0277:             * Replace each PhiCatchStmt with assignments at its operands' defs.
0278:             */
0279:            private void replaceCatchPhis(final FlowGraph cfg) {
0280:                cfg.visit(new TreeVisitor() {
0281:                    HashMap seen = new HashMap();
0282:
0283:                    public void visitFlowGraph(final FlowGraph graph) {
0284:                        final Iterator iter = graph.catchBlocks().iterator();
0285:
0286:                        // Examine each block that begins an exception handler
0287:                        while (iter.hasNext()) {
0288:                            final Block block = (Block) iter.next();
0289:                            block.visit(this );
0290:                        }
0291:                    }
0292:
0293:                    public void visitPhiCatchStmt(final PhiCatchStmt phi) {
0294:                        final LocalExpr target = (LocalExpr) phi.target();
0295:                        final int index = target.index();
0296:
0297:                        final Iterator iter = phi.operands().iterator();
0298:
0299:                        // Examine every operand of the PhiCatchStmt. If necessary,
0300:                        // insert copies of the operand to the target after the last
0301:                        // occurrence of the operand.
0302:                        while (iter.hasNext()) {
0303:                            final LocalExpr expr = (LocalExpr) iter.next();
0304:                            final LocalExpr def = (LocalExpr) expr.def();
0305:
0306:                            if (def == null) {
0307:                                continue;
0308:                            }
0309:
0310:                            if (CodeGenerator.DEBUG) {
0311:                                System.out.println("inserting for " + phi
0312:                                        + " at " + def);
0313:                            }
0314:
0315:                            BitSet s = (BitSet) seen.get(def);
0316:
0317:                            if (s == null) {
0318:                                s = new BitSet();
0319:                                seen.put(def, s);
0320:
0321:                                final BitSet t = s;
0322:
0323:                                // Visit the parent expression and make note of which
0324:                                // local variables were encountered in StoreExprs. That
0325:                                // is, have we already generated a copy for the operand
0326:                                // of
0327:                                // interest?
0328:                                def.parent().visit(new TreeVisitor() {
0329:                                    public void visitStoreExpr(
0330:                                            final StoreExpr expr) {
0331:                                        if (CodeGenerator.DEBUG) {
0332:                                            System.out
0333:                                                    .println("    merging with "
0334:                                                            + expr);
0335:                                        }
0336:
0337:                                        final Expr lhs = expr.target();
0338:                                        final Expr rhs = expr.expr();
0339:
0340:                                        if (lhs instanceof  LocalExpr) {
0341:                                            t.set(((LocalExpr) lhs).index());
0342:                                        }
0343:
0344:                                        if (rhs instanceof  LocalExpr) {
0345:                                            t.set(((LocalExpr) rhs).index());
0346:
0347:                                        } else if (rhs instanceof  StoreExpr) {
0348:                                            // Visit RHS. LHS be ignored by visitNode.
0349:                                            super .visitStoreExpr(expr);
0350:                                        }
0351:                                    }
0352:
0353:                                    public void visitNode(final Node node) {
0354:                                    }
0355:                                });
0356:                            }
0357:
0358:                            // If we've already inserted a copy (StoreStmt) for the
0359:                            // local variable, skip it
0360:                            if (s.get(index)) {
0361:                                continue;
0362:                            }
0363:
0364:                            s.set(index);
0365:
0366:                            Assert.isTrue(def != null);
0367:
0368:                            if (def.parent() instanceof  Stmt) {
0369:                                // Insert a new Stmt to copy into the target
0370:
0371:                                final Stmt stmt = (Stmt) def.parent();
0372:                                final Stmt store = createStore(target, def);
0373:                                def.block().tree().addStmtAfter(store, stmt);
0374:
0375:                            } else {
0376:                                Assert
0377:                                        .isTrue(def.parent() instanceof  StoreExpr);
0378:
0379:                                // Replace s := r with s := (t := r)
0380:                                final StoreExpr p = (StoreExpr) def.parent();
0381:                                final Expr rhs = p.expr();
0382:
0383:                                if ((rhs instanceof  LocalExpr)
0384:                                        && (((LocalExpr) rhs).index() == def
0385:                                                .index())) {
0386:                                    // No need to insert a copy. Just change the index
0387:                                    // (local variable to which LocalExpr is assigned)
0388:                                    // to be
0389:                                    // the same as the target
0390:                                    def.setIndex(index);
0391:
0392:                                } else {
0393:                                    rhs.setParent(null);
0394:
0395:                                    // Copy the rhs into the target
0396:                                    final StoreExpr store = new StoreExpr(
0397:                                            (LocalExpr) target.clone(), rhs,
0398:                                            rhs.type());
0399:
0400:                                    p.visit(new ReplaceVisitor(rhs, store));
0401:                                }
0402:                            }
0403:                        }
0404:                    }
0405:
0406:                    public void visitStmt(final Stmt stmt) {
0407:                    }
0408:                });
0409:            }
0410:
0411:            /**
0412:             * Replace PhiJoinStmts with assignments at the end of the predecessor
0413:             * blocks. Note that from now on the FUD chains are broken since there can
0414:             * be more than one def of a variable.
0415:             */
0416:            private void replaceJoinPhis(final FlowGraph cfg) {
0417:                // Go in trace order since liveness was computed under this
0418:                // assumption.
0419:
0420:                final Iterator iter = cfg.trace().iterator();
0421:
0422:                while (iter.hasNext()) {
0423:                    final Block block = (Block) iter.next();
0424:
0425:                    if (block == cfg.sink()) {
0426:                        continue;
0427:                    }
0428:
0429:                    block.visit(new TreeVisitor() {
0430:                        public void visitPhiJoinStmt(final PhiJoinStmt stmt) {
0431:                            // If an operand of the Phi statement is undefined, insert
0432:                            // code to assign 0 to the operand. The value should never
0433:                            // be used, but the verifier will squawk about using an
0434:                            // undefined local variable.
0435:
0436:                            final Iterator preds = cfg.preds(stmt.block())
0437:                                    .iterator();
0438:
0439:                            while (preds.hasNext()) {
0440:                                final Block pred = (Block) preds.next();
0441:
0442:                                final Expr operand = stmt.operandAt(pred);
0443:
0444:                                if ((stmt.target() instanceof  LocalExpr)
0445:                                        && (operand instanceof  LocalExpr)) {
0446:
0447:                                    final LocalExpr t = (LocalExpr) stmt
0448:                                            .target();
0449:                                    final LocalExpr s = (LocalExpr) operand;
0450:
0451:                                    if (t.index() == s.index()) {
0452:                                        // The target and the operand are already
0453:                                        // allocated to
0454:                                        // the same variable. Don't bother making a
0455:                                        // copy.
0456:                                        continue;
0457:                                    }
0458:                                }
0459:
0460:                                final Tree tree = pred.tree();
0461:
0462:                                // Insert stores before the last stmt to ensure
0463:                                // we don't redefine locals used the the branch stmt.
0464:                                final Stmt last = tree.lastStmt();
0465:
0466:                                last.visitChildren(new TreeVisitor() {
0467:                                    // The last statement in the block should be a jump.
0468:                                    // If
0469:                                    // the jump statement contains an expression,
0470:                                    // replace
0471:                                    // that expression with a stack variable. Before the
0472:                                    // jump, insert a store of the expression into the
0473:                                    // stack
0474:                                    // variable. This is done so that the store to the
0475:                                    // PhiJoinStmt's operand does not interfere with any
0476:                                    // local variables that might appear in the
0477:                                    // expression.
0478:                                    //
0479:                                    // operand = ...
0480:                                    // JUMP (exp)
0481:                                    // |
0482:                                    // v
0483:                                    // target = PhiJoin(operand)
0484:                                    // ...
0485:                                    // Becomes
0486:                                    //
0487:                                    // operand = ...
0488:                                    // var = exp
0489:                                    // target = operand
0490:                                    // JUMP (var)
0491:                                    // |
0492:                                    // v
0493:                                    // target = PhiJoin(operand) // Removed later
0494:                                    // ...
0495:
0496:                                    public void visitExpr(final Expr expr) {
0497:                                        StackExpr var = tree.newStack(expr
0498:                                                .type());
0499:                                        var.setValueNumber(expr.valueNumber());
0500:
0501:                                        final Node p = expr.parent();
0502:                                        expr.setParent(null);
0503:                                        p.visit(new ReplaceVisitor(expr, var));
0504:
0505:                                        var = (StackExpr) var.clone();
0506:                                        final StoreExpr store = new StoreExpr(
0507:                                                var, expr, expr.type());
0508:                                        store
0509:                                                .setValueNumber(expr
0510:                                                        .valueNumber());
0511:
0512:                                        final Stmt storeStmt = new ExprStmt(
0513:                                                store);
0514:                                        storeStmt.setValueNumber(expr
0515:                                                .valueNumber());
0516:
0517:                                        tree.addStmtBeforeJump(storeStmt);
0518:                                    }
0519:
0520:                                    public void visitStackExpr(
0521:                                            final StackExpr expr) {
0522:                                    }
0523:                                });
0524:
0525:                                final Stmt store = createStore(stmt.target(),
0526:                                        operand);
0527:
0528:                                if (CodeGenerator.DEBUG) {
0529:                                    System.out.println("insert for " + stmt
0530:                                            + " " + store + " in " + pred);
0531:                                }
0532:
0533:                                tree.addStmtBeforeJump(store);
0534:                            }
0535:                        }
0536:
0537:                        public void visitStmt(final Stmt stmt) {
0538:                        }
0539:                    });
0540:                }
0541:            }
0542:
0543:            /**
0544:             * Removes blocks that contain no other statements than gotos, jumps,
0545:             * returns, or labels. Other blocks that are invovled with the blocks being
0546:             * removed are updated appropriately.
0547:             */
0548:            private void removeEmptyBlocks(final FlowGraph cfg) {
0549:                final Set emptyBlocks = new HashSet();
0550:
0551:                Iterator e = cfg.nodes().iterator();
0552:
0553:                BLOCKS: while (e.hasNext()) {
0554:                    final Block block = (Block) e.next();
0555:
0556:                    // Collect any blocks that contain only gotos,
0557:                    // jsrs, rets, or labels.
0558:                    final Iterator stmts = block.tree().stmts().iterator();
0559:
0560:                    while (stmts.hasNext()) {
0561:                        final Stmt stmt = (Stmt) stmts.next();
0562:
0563:                        if ((stmt instanceof  GotoStmt)
0564:                                || (stmt instanceof  JsrStmt)
0565:                                || (stmt instanceof  RetStmt)
0566:                                || (stmt instanceof  LabelStmt)) {
0567:                            continue;
0568:                        }
0569:
0570:                        // The block contains something other than the above, it is
0571:                        // not empty.
0572:                        continue BLOCKS;
0573:                    }
0574:
0575:                    emptyBlocks.add(block);
0576:                }
0577:
0578:                // We want to keep the source, init, and sink blocks even if
0579:                // they're empty
0580:                emptyBlocks.remove(cfg.source());
0581:                emptyBlocks.remove(cfg.init());
0582:                emptyBlocks.remove(cfg.sink());
0583:
0584:                // Did the CFG change?
0585:                boolean changed = true;
0586:
0587:                while (changed) {
0588:                    changed = false;
0589:
0590:                    // Exclude the blocks that are control dependent on other blocks.
0591:                    final Set empty = new HashSet(emptyBlocks);
0592:                    empty.removeAll(cfg.iteratedPdomFrontier(cfg.nodes()));
0593:
0594:                    e = empty.iterator();
0595:
0596:                    while (e.hasNext()) {
0597:                        final Block block = (Block) e.next();
0598:
0599:                        if (CodeGenerator.DEBUG) {
0600:                            System.out.println("removing empty " + block);
0601:                        }
0602:
0603:                        final Stmt last = block.tree().lastStmt();
0604:
0605:                        Assert.isTrue((last instanceof  GotoStmt)
0606:                                || (last instanceof  JsrStmt)
0607:                                || (last instanceof  RetStmt));
0608:
0609:                        if (last instanceof  GotoStmt) {
0610:                            // All a block does is jump to another block
0611:                            //
0612:                            // jmp ... L
0613:                            // L: goto M
0614:                            // =>
0615:                            // jmp ... M
0616:                            final Block target = ((GotoStmt) last).target();
0617:
0618:                            final Iterator preds = new ImmutableIterator(cfg
0619:                                    .preds(block));
0620:
0621:                            while (preds.hasNext()) {
0622:                                final Block pred = (Block) preds.next();
0623:                                Assert.isTrue(pred != cfg.source());
0624:
0625:                                final Stmt predLast = pred.tree().lastStmt();
0626:                                predLast
0627:                                        .visit(new ReplaceTarget(block, target));
0628:
0629:                                cfg.removeEdge(pred, block);
0630:                                cfg.addEdge(pred, target);
0631:
0632:                                changed = true;
0633:                            }
0634:
0635:                        } else if (last instanceof  RetStmt) {
0636:                            // All a subroutine does is return
0637:
0638:                            final Iterator preds = new ImmutableIterator(cfg
0639:                                    .preds(block));
0640:
0641:                            while (preds.hasNext()) {
0642:                                final Block pred = (Block) preds.next();
0643:                                Assert.isTrue(pred != cfg.source());
0644:
0645:                                final Stmt predLast = pred.tree().lastStmt();
0646:
0647:                                if (predLast instanceof  JsrStmt) {
0648:                                    // The previous block is the jsr...
0649:                                    //
0650:                                    // jsr L ret to M
0651:                                    // M: ...
0652:                                    // L: ret // The body of the subroutine is empty
0653:                                    // =>
0654:                                    // goto M
0655:                                    // M: ...
0656:
0657:                                    final JsrStmt stmt = (JsrStmt) predLast;
0658:
0659:                                    final JumpStmt jump = new GotoStmt(stmt
0660:                                            .follow());
0661:                                    jump.catchTargets().addAll(
0662:                                            stmt.catchTargets());
0663:                                    stmt.replaceWith(jump);
0664:
0665:                                    stmt.sub().removePathsContaining(pred);
0666:
0667:                                } else if (predLast instanceof  GotoStmt) {
0668:                                    // The previous block ends in a goto. Move the ret
0669:                                    // up
0670:                                    // into the previous block, update catch targets of
0671:                                    // any
0672:                                    // exceptions thrown by the block terminated by the
0673:                                    // jump, and update the subroutine's exit block to
0674:                                    // be
0675:                                    // the previous block (in which the ret now
0676:                                    // resides).
0677:
0678:                                    final JumpStmt jump = (RetStmt) last
0679:                                            .clone();
0680:                                    jump.catchTargets().addAll(
0681:                                            ((JumpStmt) predLast)
0682:                                                    .catchTargets());
0683:                                    predLast.replaceWith(jump);
0684:                                    ((RetStmt) last).sub().setExit(pred);
0685:                                }
0686:
0687:                                // Remove the block from the CFG
0688:                                cfg.succs(pred).remove(block);
0689:                                cfg.succs(pred).addAll(cfg.succs(block));
0690:
0691:                                changed = true;
0692:                            }
0693:
0694:                        } else if (last instanceof  JsrStmt) {
0695:                            // All the block does is a jsr
0696:                            //
0697:                            // goto L
0698:                            // L: jsr M
0699:                            // =>
0700:                            // jsr M
0701:                            // L: jsr M
0702:                            final Iterator preds = new ImmutableIterator(cfg
0703:                                    .preds(block));
0704:
0705:                            while (preds.hasNext()) {
0706:                                final Block pred = (Block) preds.next();
0707:                                Assert.isTrue(pred != cfg.source());
0708:
0709:                                final Stmt predLast = pred.tree().lastStmt();
0710:
0711:                                if (predLast instanceof  GotoStmt) {
0712:                                    final JsrStmt stmt = (JsrStmt) last;
0713:
0714:                                    final JumpStmt jump = new JsrStmt(stmt
0715:                                            .sub(), stmt.follow());
0716:                                    jump.catchTargets().addAll(
0717:                                            ((JumpStmt) predLast)
0718:                                                    .catchTargets());
0719:                                    predLast.replaceWith(jump);
0720:
0721:                                    // The block is no longer a viable caller of the
0722:                                    // subroutine
0723:                                    stmt.sub().removePathsContaining(block);
0724:                                    stmt.sub().addPath(pred, stmt.follow());
0725:
0726:                                    cfg.addEdge(pred, stmt.sub().entry());
0727:                                    cfg.removeEdge(pred, block);
0728:
0729:                                    changed = true;
0730:                                }
0731:                            }
0732:
0733:                        } else {
0734:                            throw new RuntimeException();
0735:                        }
0736:                    }
0737:
0738:                    if (changed) {
0739:                        cfg.removeUnreachable();
0740:
0741:                        // Remove any empty blocks that we've already deleted.
0742:                        emptyBlocks.retainAll(cfg.nodes());
0743:                    }
0744:                }
0745:            }
0746:
0747:            /**
0748:             * Allocate "registers" (LocalVariables) for the return addresses for each
0749:             * subroutine in the method.
0750:             * 
0751:             * @param cfg
0752:             *            Control flow graph for the method
0753:             * @param alloc
0754:             *            Allocation (and information about) the local variables in the
0755:             *            method.
0756:             * 
0757:             * @see LocalVariable
0758:             * @see LocalExpr
0759:             */
0760:            public void allocReturnAddresses(final FlowGraph cfg,
0761:                    final RegisterAllocator alloc) {
0762:                // Allocate registers for the returnAddresses. Don't bother trying
0763:                // to minimize the number of locals, just get a new one.
0764:                final Iterator e = cfg.subroutines().iterator();
0765:
0766:                while (e.hasNext()) {
0767:                    final Subroutine sub = (Subroutine) e.next();
0768:                    final LocalVariable var = alloc.newLocal(Type.ADDRESS);
0769:                    sub.setReturnAddress(var);
0770:                }
0771:            }
0772:
0773:            /**
0774:             * Create a ExprStmt that initializes a target variable to a default value
0775:             * based on the type of the target.
0776:             */
0777:            protected Stmt createUndefinedStore(final VarExpr target) {
0778:                if (target.type().isReference()) {
0779:                    return new ExprStmt(new StoreExpr(target, new ConstantExpr(
0780:                            null, Type.OBJECT), target.type()));
0781:                }
0782:
0783:                if (target.type().isIntegral()) {
0784:                    return new ExprStmt(new StoreExpr(target, new ConstantExpr(
0785:                            new Integer(0), Type.INTEGER), target.type()));
0786:                }
0787:
0788:                if (target.type().equals(Type.LONG)) {
0789:                    return new ExprStmt(new StoreExpr(target, new ConstantExpr(
0790:                            new Long(0), Type.LONG), target.type()));
0791:                }
0792:
0793:                if (target.type().equals(Type.FLOAT)) {
0794:                    return new ExprStmt(new StoreExpr(target, new ConstantExpr(
0795:                            new Float(0.0F), Type.FLOAT), target.type()));
0796:                }
0797:
0798:                if (target.type().equals(Type.DOUBLE)) {
0799:                    return new ExprStmt(new StoreExpr(target, new ConstantExpr(
0800:                            new Double(0.0), Type.DOUBLE), target.type()));
0801:                }
0802:
0803:                throw new RuntimeException("Illegal type: " + target.type());
0804:            }
0805:
0806:            /**
0807:             * Returns an ExprStmt that contains a store of the source into the target.
0808:             */
0809:            protected Stmt createStore(VarExpr target, final Expr source) {
0810:                target = (VarExpr) target.clone();
0811:
0812:                // Source is an undefined variable, initialize it
0813:                if ((source instanceof  VarExpr) && (source.def() == null)) {
0814:                    return createUndefinedStore(target);
0815:                }
0816:
0817:                return new ExprStmt(new StoreExpr(target,
0818:                        (Expr) source.clone(), target.type()));
0819:            }
0820:
0821:            /*
0822:             * Using an InstructionVisitor generate the code...
0823:             */
0824:
0825:            // Several of the visit methods contain code for stack
0826:            // optimization (place dups and swaps and eliminate temporary
0827:            // variables). Nodes where swaps are to be placed are so
0828:            // marked. The markings may appear at IfCmpStmt, InitStmt,
0829:            // StoreExpr, ArithExpr, ArrayRefExpr, CallMethodExpr,
0830:            // CallStaticExpr, NewMultiArrayExpr, ShiftExpr.
0831:            public void visitExpr(final Expr expr) {
0832:                throw new RuntimeException("Unhandled expression type: "
0833:                        + expr.getClass().getName());
0834:            }
0835:
0836:            public void visitExprStmt(final ExprStmt stmt) {
0837:                if (CodeGenerator.DEBUG) {
0838:                    System.out.println("code for " + stmt);
0839:                }
0840:
0841:                stmt.visitChildren(this );
0842:
0843:                genPostponed(stmt);
0844:
0845:                if (!(stmt.expr() instanceof  StoreExpr)) {
0846:                    if (!stmt.expr().type().isVoid()) {
0847:                        if (stmt.expr().type().isWide()) {
0848:                            method.addInstruction(Opcode.opcx_pop2);
0849:                            stackHeight -= 2;
0850:
0851:                        } else {
0852:                            method.addInstruction(Opcode.opcx_pop);
0853:                            stackHeight -= 1;
0854:                        }
0855:                    }
0856:                }
0857:            }
0858:
0859:            public void visitInitStmt(final InitStmt stmt) {
0860:                if (CodeGenerator.DEBUG) {
0861:                    System.out.println("code for " + stmt);
0862:                }
0863:            }
0864:
0865:            public void visitGotoStmt(final GotoStmt stmt) {
0866:                if (CodeGenerator.DEBUG) {
0867:                    System.out.println("code for " + stmt);
0868:                }
0869:
0870:                genPostponed(stmt);
0871:
0872:                final Block target = stmt.target();
0873:
0874:                if (target != next) {
0875:                    method.addInstruction(Opcode.opcx_goto, stmt.target()
0876:                            .label());
0877:                }
0878:            }
0879:
0880:            public void visitIfCmpStmt(final IfCmpStmt stmt) {
0881:                if (CodeGenerator.DEBUG) {
0882:                    System.out.println("code for " + stmt);
0883:                }
0884:
0885:                final Block t = stmt.trueTarget();
0886:                final Block f = stmt.falseTarget();
0887:
0888:                if (f == next) {
0889:                    // Fall through to the false branch.
0890:                    genIfCmpStmt(stmt);
0891:
0892:                } else if (t == next) {
0893:                    // Fall through to the true branch.
0894:                    stmt.negate();
0895:                    genIfCmpStmt(stmt);
0896:
0897:                } else {
0898:                    // Generate a goto to the false branch after the if statement.
0899:                    genIfCmpStmt(stmt);
0900:
0901:                    method.addLabel(method.newLabelTrue()); // Tom changed to say "True"
0902:                    method.addInstruction(Opcode.opcx_goto, f.label());
0903:                }
0904:            }
0905:
0906:            private void genIfCmpStmt(final IfCmpStmt stmt) {
0907:                int opcode;
0908:
0909:                stmt.visitChildren(this );
0910:
0911:                genPostponed(stmt);
0912:
0913:                final int cmp = stmt.comparison();
0914:
0915:                if (stmt.left().type().isReference()) {
0916:                    Assert.isTrue(stmt.right().type().isReference(),
0917:                            "Illegal statement: " + stmt);
0918:
0919:                    switch (cmp) {
0920:                    case IfStmt.EQ:
0921:                        opcode = Opcode.opcx_if_acmpeq;
0922:                        break;
0923:                    case IfStmt.NE:
0924:                        opcode = Opcode.opcx_if_acmpne;
0925:                        break;
0926:                    default:
0927:                        throw new RuntimeException();
0928:                    }
0929:
0930:                } else {
0931:                    Assert.isTrue(stmt.left().type().isIntegral(),
0932:                            "Illegal statement: " + stmt);
0933:                    Assert.isTrue(stmt.right().type().isIntegral(),
0934:                            "Illegal statement: " + stmt);
0935:
0936:                    switch (cmp) {
0937:                    case IfStmt.EQ:
0938:                        opcode = Opcode.opcx_if_icmpeq;
0939:                        break;
0940:                    case IfStmt.NE:
0941:                        opcode = Opcode.opcx_if_icmpne;
0942:                        break;
0943:                    case IfStmt.GT:
0944:                        opcode = Opcode.opcx_if_icmpgt;
0945:                        break;
0946:                    case IfStmt.GE:
0947:                        opcode = Opcode.opcx_if_icmpge;
0948:                        break;
0949:                    case IfStmt.LT:
0950:                        opcode = Opcode.opcx_if_icmplt;
0951:                        break;
0952:                    case IfStmt.LE:
0953:                        opcode = Opcode.opcx_if_icmple;
0954:                        break;
0955:                    default:
0956:                        throw new RuntimeException();
0957:                    }
0958:                }
0959:
0960:                method.addInstruction(opcode, stmt.trueTarget().label());
0961:                stackHeight -= 2;
0962:            }
0963:
0964:            public void visitIfZeroStmt(final IfZeroStmt stmt) {
0965:                if (CodeGenerator.DEBUG) {
0966:                    System.out.println("code for " + stmt);
0967:                }
0968:
0969:                final Block t = stmt.trueTarget();
0970:                final Block f = stmt.falseTarget();
0971:
0972:                if (f == next) {
0973:                    // Fall through to the false branch.
0974:                    genIfZeroStmt(stmt);
0975:                } else if (t == next) {
0976:                    // Fall through to the true branch.
0977:                    stmt.negate();
0978:                    genIfZeroStmt(stmt);
0979:                } else {
0980:                    // Generate a goto to the false branch after the if statement.
0981:                    genIfZeroStmt(stmt);
0982:                    method.addLabel(method.newLabelTrue()); // Tom added "True"
0983:                    method.addInstruction(Opcode.opcx_goto, f.label());
0984:                }
0985:            }
0986:
0987:            private void genIfZeroStmt(final IfZeroStmt stmt) {
0988:                int opcode;
0989:
0990:                stmt.expr().visit(this );
0991:
0992:                genPostponed(stmt);
0993:
0994:                final int cmp = stmt.comparison();
0995:
0996:                if (stmt.expr().type().isReference()) {
0997:                    switch (cmp) {
0998:                    case IfStmt.EQ:
0999:                        opcode = Opcode.opcx_ifnull;
1000:                        break;
1001:                    case IfStmt.NE:
1002:                        opcode = Opcode.opcx_ifnonnull;
1003:                        break;
1004:                    default:
1005:                        throw new RuntimeException();
1006:                    }
1007:
1008:                } else {
1009:                    Assert.isTrue(stmt.expr().type().isIntegral(),
1010:                            "Illegal statement: " + stmt);
1011:
1012:                    switch (cmp) {
1013:                    case IfStmt.EQ:
1014:                        opcode = Opcode.opcx_ifeq;
1015:                        break;
1016:                    case IfStmt.NE:
1017:                        opcode = Opcode.opcx_ifne;
1018:                        break;
1019:                    case IfStmt.GT:
1020:                        opcode = Opcode.opcx_ifgt;
1021:                        break;
1022:                    case IfStmt.GE:
1023:                        opcode = Opcode.opcx_ifge;
1024:                        break;
1025:                    case IfStmt.LT:
1026:                        opcode = Opcode.opcx_iflt;
1027:                        break;
1028:                    case IfStmt.LE:
1029:                        opcode = Opcode.opcx_ifle;
1030:                        break;
1031:                    default:
1032:                        throw new RuntimeException();
1033:                    }
1034:                }
1035:                method.addInstruction(opcode, stmt.trueTarget().label());
1036:                stackHeight -= 1;
1037:            }
1038:
1039:            public void visitLabelStmt(final LabelStmt stmt) {
1040:                if (CodeGenerator.DEBUG) {
1041:                    System.out.println("code for " + stmt);
1042:                }
1043:
1044:                stmt.visitChildren(this );
1045:
1046:                genPostponed(stmt);
1047:
1048:                method.addLabel(stmt.label());
1049:            }
1050:
1051:            public void visitMonitorStmt(final MonitorStmt stmt) {
1052:                if (CodeGenerator.DEBUG) {
1053:                    System.out.println("code for " + stmt);
1054:                }
1055:
1056:                stmt.visitChildren(this );
1057:
1058:                genPostponed(stmt);
1059:
1060:                if (stmt.kind() == MonitorStmt.ENTER) {
1061:                    method.addInstruction(Opcode.opcx_monitorenter);
1062:                    stackHeight -= 1;
1063:
1064:                } else if (stmt.kind() == MonitorStmt.EXIT) {
1065:                    method.addInstruction(Opcode.opcx_monitorexit);
1066:                    stackHeight -= 1;
1067:
1068:                } else {
1069:                    throw new IllegalArgumentException();
1070:                }
1071:            }
1072:
1073:            public void visitPhiStmt(final PhiStmt stmt) {
1074:                throw new RuntimeException("Cannot generate code for " + stmt);
1075:            }
1076:
1077:            public void visitRCExpr(final RCExpr expr) {
1078:                expr.visitChildren(this );
1079:
1080:                genPostponed(expr);
1081:
1082:                // Move the rc forward as far as possible.
1083:                //
1084:                // For example, for the expression:
1085:                //
1086:                // rc(x).m(rc(a).b)
1087:                //
1088:                // we want to generate:
1089:                //
1090:                // aload x
1091:                // aload a
1092:                // rc 0
1093:                // getfield <A.b>
1094:                // rc 1
1095:                // invoke <X.m>
1096:                //
1097:                // rather than:
1098:                //
1099:                // aload x
1100:                // rc 0
1101:                // aload a
1102:                // rc 0
1103:                // getfield <A.b>
1104:                // invoke <X.m>
1105:                //
1106:                Instruction postpone = null;
1107:
1108:                Node parent = expr.parent();
1109:
1110:                // If the parent is wrapped in a ZeroCheckExpr, then look at the
1111:                // parent's parent.
1112:
1113:                if (parent instanceof  ZeroCheckExpr) {
1114:                    parent = parent.parent();
1115:                }
1116:
1117:                // If the depth is going to be > 0, postpone the rc instruction
1118:                // to just before the getfield, putfield, invoke, xaload, xastore, etc.
1119:                // If the stack depth for the rc is going to be 0, the rc will (be)
1120:                // the next instruction generated anyway, so don't postpone.
1121:
1122:                if (parent instanceof  ArrayRefExpr) {
1123:                    final ArrayRefExpr p = (ArrayRefExpr) parent;
1124:
1125:                    if (expr == p.array()) {
1126:                        if (p.isDef()) {
1127:                            // a[i] := r
1128:                            // Stack at the xastore: ... a i r
1129:                            postpone = new Instruction(Opcode.opcx_rc,
1130:                                    new Integer(p.type().stackHeight() + 1));
1131:                        } else {
1132:                            // use a[i]
1133:                            // Stack at the xaload: ... a i
1134:                            postpone = new Instruction(Opcode.opcx_rc,
1135:                                    new Integer(1));
1136:                        }
1137:                    }
1138:
1139:                } else if (parent instanceof  CallMethodExpr) {
1140:                    final CallMethodExpr p = (CallMethodExpr) parent;
1141:
1142:                    if (expr == p.receiver()) {
1143:                        // a.m(b, c)
1144:                        // Stack at the invoke: ... a b c
1145:                        final MemberRef method = p.method();
1146:                        final int depth = method.nameAndType().type()
1147:                                .stackHeight();
1148:                        postpone = new Instruction(Opcode.opcx_rc, new Integer(
1149:                                depth));
1150:                    }
1151:
1152:                } else if (parent instanceof  FieldExpr) {
1153:                    final FieldExpr p = (FieldExpr) parent;
1154:
1155:                    if (expr == p.object()) {
1156:                        if (p.isDef()) {
1157:                            // a.b := r
1158:                            // Stack at the putfield: ... a r
1159:                            postpone = new Instruction(Opcode.opcx_rc,
1160:                                    new Integer(p.type().stackHeight()));
1161:                        }
1162:                    }
1163:                }
1164:
1165:                if (postpone == null) {
1166:                    int depth = 0;
1167:
1168:                    if (expr.expr() instanceof  StackExpr) {
1169:                        // If the rc works on a StackExpr, calculate its depth in the
1170:                        // stack. In all other cases, the rc will operate on whatever
1171:                        // is on top of the stack.
1172:                        final StackExpr stackVar = (StackExpr) expr.expr();
1173:                        depth = stackHeight - stackVar.index() - 1;
1174:                    }
1175:
1176:                    method.addInstruction(Opcode.opcx_rc, new Integer(depth));
1177:
1178:                } else {
1179:                    postponedInstructions.put(parent, postpone);
1180:                }
1181:            }
1182:
1183:            public void visitUCExpr(final UCExpr expr) {
1184:                expr.visitChildren(this );
1185:
1186:                if (true) {
1187:                    return;
1188:                }
1189:
1190:                genPostponed(expr);
1191:
1192:                // Move the uc forward as far as possible.
1193:                Instruction postpone = null;
1194:
1195:                final Node parent = expr.parent();
1196:
1197:                // If the depth is going to be > 0, postpone the uc instruction
1198:                // to just before the putfield. If the stack depth for the
1199:                // uc is going to be 0, the uc will the next instruction
1200:                // generated anyway, so don't postpone.
1201:
1202:                if (parent instanceof  FieldExpr) {
1203:                    final FieldExpr p = (FieldExpr) parent;
1204:
1205:                    if (expr == p.object()) {
1206:                        if (p.isDef()) {
1207:                            // a.b := r
1208:                            // Stack at the putfield: ... a r
1209:                            if (expr.kind() == UCExpr.POINTER) {
1210:                                postpone = new Instruction(Opcode.opcx_aupdate,
1211:                                        new Integer(p.type().stackHeight()));
1212:
1213:                            } else if (expr.kind() == UCExpr.SCALAR) {
1214:                                postpone = new Instruction(Opcode.opcx_supdate,
1215:                                        new Integer(p.type().stackHeight()));
1216:
1217:                            } else {
1218:                                throw new RuntimeException();
1219:                            }
1220:                        }
1221:                    }
1222:                }
1223:
1224:                if (postpone == null) {
1225:                    int depth = 0;
1226:
1227:                    if (expr.expr() instanceof  StackExpr) {
1228:                        // If the UCExpr operates on a stack variable, use that to
1229:                        // determine the depth. In all other cases, use 0.
1230:                        final StackExpr stackVar = (StackExpr) expr.expr();
1231:                        depth = stackHeight - stackVar.index() - 1;
1232:                    }
1233:
1234:                    if (expr.kind() == UCExpr.POINTER) {
1235:                        method.addInstruction(Opcode.opcx_aupdate, new Integer(
1236:                                depth));
1237:                    } else if (expr.kind() == UCExpr.SCALAR) {
1238:                        method.addInstruction(Opcode.opcx_supdate, new Integer(
1239:                                depth));
1240:                    } else {
1241:                        throw new RuntimeException();
1242:                    }
1243:
1244:                } else {
1245:                    postponedInstructions.put(parent, postpone);
1246:                }
1247:            }
1248:
1249:            public void visitRetStmt(final RetStmt stmt) {
1250:                if (CodeGenerator.DEBUG) {
1251:                    System.out.println("code for " + stmt);
1252:                }
1253:
1254:                genPostponed(stmt);
1255:
1256:                final Subroutine sub = stmt.sub();
1257:                Assert.isTrue(sub.returnAddress() != null);
1258:                method.addInstruction(Opcode.opcx_ret, sub.returnAddress());
1259:            }
1260:
1261:            public void visitReturnExprStmt(final ReturnExprStmt stmt) {
1262:                if (CodeGenerator.DEBUG) {
1263:                    System.out.println("code for " + stmt);
1264:                }
1265:
1266:                stmt.visitChildren(this );
1267:
1268:                genPostponed(stmt);
1269:
1270:                final Type type = stmt.expr().type();
1271:
1272:                // Stack should be empty after return
1273:
1274:                if (type.isReference()) {
1275:                    method.addInstruction(Opcode.opcx_areturn);
1276:                    stackHeight = 0;
1277:                } else if (type.isIntegral()) {
1278:                    method.addInstruction(Opcode.opcx_ireturn);
1279:                    stackHeight = 0;
1280:                } else if (type.equals(Type.LONG)) {
1281:                    method.addInstruction(Opcode.opcx_lreturn);
1282:                    stackHeight = 0;
1283:                } else if (type.equals(Type.FLOAT)) {
1284:                    method.addInstruction(Opcode.opcx_freturn);
1285:                    stackHeight = 0;
1286:                } else if (type.equals(Type.DOUBLE)) {
1287:                    method.addInstruction(Opcode.opcx_dreturn);
1288:                    stackHeight = 0;
1289:                }
1290:            }
1291:
1292:            public void visitReturnStmt(final ReturnStmt stmt) {
1293:                if (CodeGenerator.DEBUG) {
1294:                    System.out.println("code for " + stmt);
1295:                }
1296:
1297:                genPostponed(stmt);
1298:
1299:                stmt.visitChildren(this );
1300:                method.addInstruction(Opcode.opcx_return);
1301:
1302:                // Stack height is zero after return
1303:                stackHeight = 0;
1304:            }
1305:
1306:            public void visitStoreExpr(final StoreExpr expr) {
1307:                if (CodeGenerator.DEBUG) {
1308:                    System.out.println("code for " + expr);
1309:                }
1310:
1311:                final MemExpr lhs = expr.target();
1312:                final Expr rhs = expr.expr();
1313:
1314:                boolean returnsValue = !(expr.parent() instanceof  ExprStmt);
1315:
1316:                // eliminate the store if the both sides have the same target
1317:
1318:                if (!returnsValue) {
1319:                    if ((lhs instanceof  LocalExpr)
1320:                            && (rhs instanceof  LocalExpr)) {
1321:
1322:                        // The second condition checks that the right sides have indeed
1323:                        // been stored-- otherwise (ie, if we're just keeping it on the
1324:                        // stack), we should not eliminate this store
1325:
1326:                        if ((((LocalExpr) lhs).index() == ((LocalExpr) rhs)
1327:                                .index())
1328:
1329:                                && (!CodeGenerator.OPT_STACK || currentSO
1330:                                        .shouldStore(((LocalExpr) ((LocalExpr) rhs)
1331:                                                .def())))) {
1332:                            return;
1333:                        }
1334:                    }
1335:
1336:                    // Special case to handle L := L + k.
1337:                    // Generate "iinc L, k" instead of "iload L; ldc k; iadd; istore L".
1338:                    //
1339:                    // TODO: for L := M + k, generate "iload M; istore L; iinc L, k".
1340:                    //
1341:
1342:                    /*
1343:                     * This next special case was modified for stack optimization. If L
1344:                     * is marked for a dup, the fact that its value is never on the
1345:                     * stack means we don't have anything to dup-- we need to load
1346:                     * instead. (Things get more complicated if it was marked for a
1347:                     * dup_x2, but that's not likely to happen)
1348:                     */
1349:
1350:                    if ((lhs instanceof  LocalExpr) && lhs.type().isIntegral()) {
1351:                        Integer value = null;
1352:                        // eliminate the store if the both sides have the same target
1353:
1354:                        final int index = ((LocalExpr) lhs).index();
1355:
1356:                        if (rhs instanceof  ArithExpr) {
1357:                            final ArithExpr arith = (ArithExpr) rhs;
1358:
1359:                            final Expr left = arith.left();
1360:                            final Expr right = arith.right();
1361:
1362:                            if ((left instanceof  LocalExpr)
1363:                                    && (index == ((LocalExpr) left).index())
1364:                                    && (right instanceof  ConstantExpr)) {
1365:
1366:                                final ConstantExpr c = (ConstantExpr) right;
1367:
1368:                                if (c.value() instanceof  Integer) {
1369:                                    value = (Integer) c.value();
1370:                                }
1371:
1372:                            } else if ((right instanceof  LocalExpr)
1373:                                    && (index == ((LocalExpr) right).index())
1374:                                    && (left instanceof  ConstantExpr)
1375:                                    && (arith.operation() == ArithExpr.ADD)) {
1376:
1377:                                // This will not work for x = c - x because it is not
1378:                                // the
1379:                                // same as x = x - c.
1380:
1381:                                final ConstantExpr c = (ConstantExpr) left;
1382:
1383:                                if (c.value() instanceof  Integer) {
1384:                                    value = (Integer) c.value();
1385:                                }
1386:                            }
1387:
1388:                            if ((value != null)
1389:                                    && (arith.operation() == ArithExpr.SUB)) {
1390:                                value = new Integer(-value.intValue());
1391:                            } else if (arith.operation() != ArithExpr.ADD) {
1392:                                value = null;
1393:                            }
1394:                        }
1395:
1396:                        if (value != null) {
1397:                            final int incr = value.intValue();
1398:
1399:                            if (incr == 0) {
1400:                                // No need to increment by 0.
1401:
1402:                                // for a better understanding of what's going on in
1403:                                // these
1404:                                // additions, see VisitLocalExpr, where we do basically
1405:                                // the
1406:                                // same thing.
1407:
1408:                                if (CodeGenerator.OPT_STACK) {
1409:                                    int dups, dup_x1s, dup_x2s;
1410:                                    dups = currentSO.dups((LocalExpr) lhs);
1411:                                    dup_x1s = currentSO
1412:                                            .dup_x1s((LocalExpr) lhs);
1413:                                    dup_x2s = currentSO
1414:                                            .dup_x2s((LocalExpr) lhs);
1415:                                    for (int i = 0; i < dup_x2s; i++) {
1416:                                        // This is really awful, but be consoled in that
1417:                                        // it is
1418:                                        // highly improbable to happen... this is just
1419:                                        // to make correct code in the chance that we
1420:                                        // have something like this.
1421:                                        method.addInstruction(Opcode.opcx_ldc,
1422:                                                new Integer(0));
1423:                                        method
1424:                                                .addInstruction(Opcode.opc_dup_x2);
1425:                                        method.addInstruction(Opcode.opc_pop);
1426:                                        stackHeight += 1;
1427:                                    }
1428:                                    for (int i = 0; i < dup_x1s; i++) {
1429:                                        method.addInstruction(Opcode.opcx_ldc,
1430:                                                new Integer(0));
1431:                                        method.addInstruction(Opcode.opc_swap);
1432:                                        stackHeight += 1;
1433:                                    }
1434:                                    for (int i = 0; i < dups; i++) {
1435:                                        method.addInstruction(Opcode.opcx_ldc,
1436:                                                new Integer(0));
1437:                                        stackHeight += 1;
1438:                                    }
1439:                                }
1440:
1441:                                return;
1442:
1443:                            } else if ((short) incr == incr) {
1444:                                // Only generate an iinc if the increment fits in
1445:                                // a short.
1446:                                method
1447:                                        .addInstruction(
1448:                                                Opcode.opcx_iinc,
1449:                                                new IncOperand(
1450:                                                        new LocalVariable(index),
1451:                                                        incr));
1452:
1453:                                if (CodeGenerator.OPT_STACK) {
1454:                                    int dups, dup_x1s, dup_x2s;
1455:                                    dups = currentSO.dups((LocalExpr) lhs);
1456:                                    dup_x1s = currentSO
1457:                                            .dup_x1s((LocalExpr) lhs);
1458:                                    dup_x2s = currentSO
1459:                                            .dup_x2s((LocalExpr) lhs);
1460:                                    for (int i = 0; i < dup_x2s; i++) {
1461:                                        method.addInstruction(
1462:                                                Opcode.opcx_istore,
1463:                                                new LocalVariable(
1464:                                                        ((LocalExpr) lhs)
1465:                                                                .index()));
1466:                                        method
1467:                                                .addInstruction(Opcode.opc_dup_x2);
1468:                                        method.addInstruction(Opcode.opc_pop);
1469:                                        stackHeight += 1;
1470:                                    }
1471:                                    for (int i = 0; i < dup_x1s; i++) {
1472:                                        method.addInstruction(
1473:                                                Opcode.opcx_iload,
1474:                                                new LocalVariable(
1475:                                                        ((LocalExpr) lhs)
1476:                                                                .index()));
1477:                                        method.addInstruction(Opcode.opc_swap);
1478:                                        stackHeight += 1;
1479:                                    }
1480:                                    for (int i = 0; i < dups; i++) {
1481:                                        method.addInstruction(
1482:                                                Opcode.opcx_iload,
1483:                                                new LocalVariable(
1484:                                                        ((LocalExpr) lhs)
1485:                                                                .index()));
1486:                                        stackHeight += 1;
1487:                                    }
1488:                                }
1489:
1490:                                return;
1491:                            }
1492:                        }
1493:                    }
1494:                }
1495:
1496:                // Generate, and return the value.
1497:                lhs.visitChildren(this );
1498:                rhs.visit(this );
1499:
1500:                if (returnsValue) {
1501:                    if (lhs instanceof  ArrayRefExpr) {
1502:                        // array index rhs --> rhs array index rhs
1503:                        if (rhs.type().isWide()) {
1504:                            method.addInstruction(Opcode.opcx_dup2_x2);
1505:                            stackHeight += 2;
1506:                        } else {
1507:                            method.addInstruction(Opcode.opcx_dup_x2);
1508:                            stackHeight += 1;
1509:                        }
1510:
1511:                    } else if (lhs instanceof  FieldExpr) {
1512:                        // object rhs --> rhs object rhs
1513:                        if (rhs.type().isWide()) {
1514:                            method.addInstruction(Opcode.opcx_dup2_x1);
1515:                            stackHeight += 2;
1516:                        } else {
1517:                            method.addInstruction(Opcode.opcx_dup_x1);
1518:                            stackHeight += 1;
1519:                        }
1520:
1521:                    } else {
1522:                        // rhs --> rhs rhs
1523:                        if (rhs.type().isWide()) {
1524:                            method.addInstruction(Opcode.opcx_dup2);
1525:                            stackHeight += 2;
1526:                        } else {
1527:                            method.addInstruction(Opcode.opcx_dup);
1528:                            stackHeight += 1;
1529:                        }
1530:                    }
1531:                }
1532:
1533:                genPostponed(expr);
1534:                lhs.visitOnly(this );
1535:            }
1536:
1537:            public void visitAddressStoreStmt(final AddressStoreStmt stmt) {
1538:                if (CodeGenerator.DEBUG) {
1539:                    System.out.println("code for " + stmt);
1540:                }
1541:
1542:                genPostponed(stmt);
1543:
1544:                final Subroutine sub = stmt.sub();
1545:                Assert.isTrue(sub.returnAddress() != null);
1546:                method.addInstruction(Opcode.opcx_astore, sub.returnAddress());
1547:                stackHeight -= 1;
1548:            }
1549:
1550:            public void visitJsrStmt(final JsrStmt stmt) {
1551:                if (CodeGenerator.DEBUG) {
1552:                    System.out.println("code for " + stmt);
1553:                }
1554:
1555:                genPostponed(stmt);
1556:
1557:                final Block entry = stmt.sub().entry();
1558:                method.addInstruction(Opcode.opcx_jsr, entry.label());
1559:                stackHeight += 1;
1560:
1561:                if (stmt.follow() != next) {
1562:                    method.addLabel(method.newLabelTrue());
1563:                    method.addInstruction(Opcode.opcx_goto, stmt.follow()
1564:                            .label());
1565:                }
1566:            }
1567:
1568:            public void visitSwitchStmt(final SwitchStmt stmt) {
1569:                if (CodeGenerator.DEBUG) {
1570:                    System.out.println("code for " + stmt);
1571:                }
1572:
1573:                stmt.visitChildren(this );
1574:
1575:                genPostponed(stmt);
1576:
1577:                final Label[] targets = new Label[stmt.targets().length];
1578:
1579:                for (int i = 0; i < targets.length; i++) {
1580:                    targets[i] = stmt.targets()[i].label();
1581:                }
1582:
1583:                method.addInstruction(Opcode.opcx_switch, new Switch(stmt
1584:                        .defaultTarget().label(), targets, stmt.values()));
1585:                stackHeight -= 1;
1586:            }
1587:
1588:            public void visitStackManipStmt(final StackManipStmt stmt) {
1589:                if (CodeGenerator.DEBUG) {
1590:                    System.out.println("code for " + stmt);
1591:                }
1592:
1593:                genPostponed(stmt);
1594:
1595:                // All the children are stack variables, so don't so anything.
1596:
1597:                switch (stmt.kind()) {
1598:                case StackManipStmt.SWAP:
1599:                    method.addInstruction(Opcode.opcx_swap);
1600:                    break;
1601:                case StackManipStmt.DUP:
1602:                    method.addInstruction(Opcode.opcx_dup);
1603:                    stackHeight += 1;
1604:                    break;
1605:                case StackManipStmt.DUP_X1:
1606:                    method.addInstruction(Opcode.opcx_dup_x1);
1607:                    stackHeight += 1;
1608:                    break;
1609:                case StackManipStmt.DUP_X2:
1610:                    method.addInstruction(Opcode.opcx_dup_x2);
1611:                    stackHeight += 1;
1612:                    break;
1613:                case StackManipStmt.DUP2:
1614:                    method.addInstruction(Opcode.opcx_dup2);
1615:                    stackHeight += 2;
1616:                    break;
1617:                case StackManipStmt.DUP2_X1:
1618:                    method.addInstruction(Opcode.opcx_dup2_x1);
1619:                    stackHeight += 2;
1620:                    break;
1621:                case StackManipStmt.DUP2_X2:
1622:                    method.addInstruction(Opcode.opcx_dup2_x2);
1623:                    stackHeight += 2;
1624:                    break;
1625:                }
1626:            }
1627:
1628:            public void visitThrowStmt(final ThrowStmt stmt) {
1629:                if (CodeGenerator.DEBUG) {
1630:                    System.out.println("code for " + stmt);
1631:                }
1632:
1633:                stmt.visitChildren(this );
1634:
1635:                genPostponed(stmt);
1636:
1637:                method.addInstruction(Opcode.opcx_athrow);
1638:            }
1639:
1640:            public void visitSCStmt(final SCStmt stmt) {
1641:                stmt.visitChildren(this );
1642:                genPostponed(stmt);
1643:                method.addInstruction(Opcode.opcx_aswizzle);
1644:                stackHeight -= 2;
1645:            }
1646:
1647:            public void visitSRStmt(final SRStmt stmt) {
1648:                stmt.visitChildren(this );
1649:                genPostponed(stmt);
1650:                method.addInstruction(Opcode.opcx_aswrange);
1651:                stackHeight -= 3;
1652:            }
1653:
1654:            public void visitArithExpr(final ArithExpr expr) {
1655:                expr.visitChildren(this );
1656:
1657:                genPostponed(expr);
1658:
1659:                final int[][] opcode = new int[][] {
1660:                        { Opcode.opcx_iadd, Opcode.opcx_ladd, Opcode.opcx_fadd,
1661:                                Opcode.opcx_dadd },
1662:                        { Opcode.opcx_iand, Opcode.opcx_land, Opcode.opcx_nop,
1663:                                Opcode.opcx_nop },
1664:                        { Opcode.opcx_idiv, Opcode.opcx_ldiv, Opcode.opcx_fdiv,
1665:                                Opcode.opcx_ddiv },
1666:                        { Opcode.opcx_imul, Opcode.opcx_lmul, Opcode.opcx_fmul,
1667:                                Opcode.opcx_dmul },
1668:                        { Opcode.opcx_ior, Opcode.opcx_lor, Opcode.opcx_nop,
1669:                                Opcode.opcx_nop },
1670:                        { Opcode.opcx_irem, Opcode.opcx_lrem, Opcode.opcx_frem,
1671:                                Opcode.opcx_drem },
1672:                        { Opcode.opcx_isub, Opcode.opcx_lsub, Opcode.opcx_fsub,
1673:                                Opcode.opcx_dsub },
1674:                        { Opcode.opcx_ixor, Opcode.opcx_lxor, Opcode.opcx_nop,
1675:                                Opcode.opcx_nop },
1676:                        { Opcode.opcx_nop, Opcode.opcx_lcmp, Opcode.opcx_nop,
1677:                                Opcode.opcx_nop },
1678:                        { Opcode.opcx_nop, Opcode.opcx_nop, Opcode.opcx_fcmpl,
1679:                                Opcode.opcx_dcmpl },
1680:                        { Opcode.opcx_nop, Opcode.opcx_nop, Opcode.opcx_fcmpg,
1681:                                Opcode.opcx_dcmpg } };
1682:
1683:                final int[][] stackChange = new int[][] { { -1, -2, -1, -2 },
1684:                        { -1, -2, 0, 0 }, { -1, -2, -1, -2 },
1685:                        { -1, -2, -1, -2 }, { -1, -2, 0, 0 },
1686:                        { -1, -2, -1, -2 }, { -1, -2, -1, -2 },
1687:                        { -1, -2, 0, 0 }, { 0, -3, 0, 0 }, { 0, 0, -1, -3 },
1688:                        { 0, 0, -1, -3 } };
1689:
1690:                int type;
1691:
1692:                if (expr.left().type().isIntegral()) {
1693:                    type = 0;
1694:
1695:                } else if (expr.left().type().equals(Type.LONG)) {
1696:                    type = 1;
1697:
1698:                } else if (expr.left().type().equals(Type.FLOAT)) {
1699:                    type = 2;
1700:
1701:                } else if (expr.left().type().equals(Type.DOUBLE)) {
1702:                    type = 3;
1703:
1704:                } else {
1705:                    throw new IllegalArgumentException(
1706:                            "Can't generate code for type: "
1707:                                    + expr.left().type() + " (expr " + expr
1708:                                    + ")");
1709:                }
1710:
1711:                switch (expr.operation()) {
1712:                case ArithExpr.ADD:
1713:                    method.addInstruction(opcode[0][type]);
1714:                    stackHeight += stackChange[0][type];
1715:                    break;
1716:                case ArithExpr.AND:
1717:                    method.addInstruction(opcode[1][type]);
1718:                    stackHeight += stackChange[1][type];
1719:                    break;
1720:                case ArithExpr.DIV:
1721:                    method.addInstruction(opcode[2][type]);
1722:                    stackHeight += stackChange[2][type];
1723:                    break;
1724:                case ArithExpr.MUL:
1725:                    method.addInstruction(opcode[3][type]);
1726:                    stackHeight += stackChange[3][type];
1727:                    break;
1728:                case ArithExpr.IOR:
1729:                    method.addInstruction(opcode[4][type]);
1730:                    stackHeight += stackChange[4][type];
1731:                    break;
1732:                case ArithExpr.REM:
1733:                    method.addInstruction(opcode[5][type]);
1734:                    stackHeight += stackChange[5][type];
1735:                    break;
1736:                case ArithExpr.SUB:
1737:                    method.addInstruction(opcode[6][type]);
1738:                    stackHeight += stackChange[6][type];
1739:                    break;
1740:                case ArithExpr.XOR:
1741:                    method.addInstruction(opcode[7][type]);
1742:                    stackHeight += stackChange[7][type];
1743:                    break;
1744:                case ArithExpr.CMP:
1745:                    method.addInstruction(opcode[8][type]);
1746:                    stackHeight += stackChange[8][type];
1747:                    break;
1748:                case ArithExpr.CMPL:
1749:                    method.addInstruction(opcode[9][type]);
1750:                    stackHeight += stackChange[9][type];
1751:                    break;
1752:                case ArithExpr.CMPG:
1753:                    method.addInstruction(opcode[10][type]);
1754:                    stackHeight += stackChange[10][type];
1755:                    break;
1756:                }
1757:            }
1758:
1759:            public void visitArrayLengthExpr(final ArrayLengthExpr expr) {
1760:                expr.visitChildren(this );
1761:                method.addInstruction(Opcode.opcx_arraylength);
1762:            }
1763:
1764:            public void visitArrayRefExpr(final ArrayRefExpr expr) {
1765:                expr.visitChildren(this );
1766:
1767:                genPostponed(expr);
1768:
1769:                int opcode;
1770:
1771:                if (expr.isDef()) {
1772:                    if (expr.elementType().isReference()) {
1773:                        opcode = Opcode.opcx_aastore;
1774:                        stackHeight -= 3;
1775:                    } else if (expr.elementType().equals(Type.BYTE)) {
1776:                        opcode = Opcode.opcx_bastore;
1777:                        stackHeight -= 3;
1778:                    } else if (expr.elementType().equals(Type.CHARACTER)) {
1779:                        opcode = Opcode.opcx_castore;
1780:                        stackHeight -= 3;
1781:                    } else if (expr.elementType().equals(Type.SHORT)) {
1782:                        opcode = Opcode.opcx_sastore;
1783:                        stackHeight -= 3;
1784:                    } else if (expr.elementType().equals(Type.INTEGER)) {
1785:                        opcode = Opcode.opcx_iastore;
1786:                        stackHeight -= 3;
1787:                    } else if (expr.elementType().equals(Type.LONG)) {
1788:                        opcode = Opcode.opcx_lastore;
1789:                        stackHeight -= 4;
1790:                    } else if (expr.elementType().equals(Type.FLOAT)) {
1791:                        opcode = Opcode.opcx_fastore;
1792:                        stackHeight -= 3;
1793:                    } else if (expr.elementType().equals(Type.DOUBLE)) {
1794:                        opcode = Opcode.opcx_dastore;
1795:                        stackHeight -= 4;
1796:                    } else {
1797:                        throw new IllegalArgumentException(
1798:                                "Can't generate code for type: " + expr.type()
1799:                                        + " (expr " + expr + ")");
1800:                    }
1801:                } else {
1802:                    if (expr.elementType().isReference()) {
1803:                        opcode = Opcode.opcx_aaload;
1804:                        stackHeight -= 1;
1805:                    } else if (expr.elementType().equals(Type.BYTE)) {
1806:                        opcode = Opcode.opcx_baload;
1807:                        stackHeight -= 1;
1808:                    } else if (expr.elementType().equals(Type.CHARACTER)) {
1809:                        opcode = Opcode.opcx_caload;
1810:                        stackHeight -= 1;
1811:                    } else if (expr.elementType().equals(Type.SHORT)) {
1812:                        opcode = Opcode.opcx_saload;
1813:                        stackHeight -= 1;
1814:                    } else if (expr.elementType().equals(Type.INTEGER)) {
1815:                        opcode = Opcode.opcx_iaload;
1816:                        stackHeight -= 1;
1817:                    } else if (expr.elementType().equals(Type.LONG)) {
1818:                        opcode = Opcode.opcx_laload;
1819:                        stackHeight -= 0;
1820:                    } else if (expr.elementType().equals(Type.FLOAT)) {
1821:                        opcode = Opcode.opcx_faload;
1822:                        stackHeight -= 1;
1823:                    } else if (expr.elementType().equals(Type.DOUBLE)) {
1824:                        opcode = Opcode.opcx_daload;
1825:                        stackHeight -= 0;
1826:                    } else {
1827:                        throw new IllegalArgumentException(
1828:                                "Can't generate code for type: " + expr.type()
1829:                                        + " (expr " + expr + ")");
1830:                    }
1831:                }
1832:
1833:                method.addInstruction(opcode);
1834:            }
1835:
1836:            public void visitCallMethodExpr(final CallMethodExpr expr) {
1837:                expr.visitChildren(this );
1838:
1839:                genPostponed(expr);
1840:
1841:                int opcode;
1842:
1843:                if (expr.kind() == CallMethodExpr.VIRTUAL) {
1844:                    opcode = Opcode.opcx_invokevirtual;
1845:                } else if (expr.kind() == CallMethodExpr.NONVIRTUAL) {
1846:                    opcode = Opcode.opcx_invokespecial;
1847:                } else if (expr.kind() == CallMethodExpr.INTERFACE) {
1848:                    opcode = Opcode.opcx_invokeinterface;
1849:                } else {
1850:                    throw new IllegalArgumentException();
1851:                }
1852:
1853:                method.addInstruction(opcode, expr.method());
1854:
1855:                // Pop reciever object off stack
1856:                stackHeight -= 1;
1857:
1858:                // Pop each parameter off stack
1859:                final Expr[] params = expr.params();
1860:                for (int i = 0; i < params.length; i++) {
1861:                    stackHeight -= params[i].type().stackHeight();
1862:                }
1863:            }
1864:
1865:            public void visitCallStaticExpr(final CallStaticExpr expr) {
1866:                expr.visitChildren(this );
1867:
1868:                genPostponed(expr);
1869:
1870:                method.addInstruction(Opcode.opcx_invokestatic, expr.method());
1871:
1872:                // Pop each parameter off stack
1873:                final Expr[] params = expr.params();
1874:                for (int i = 0; i < params.length; i++) {
1875:                    stackHeight -= params[i].type().stackHeight();
1876:                }
1877:            }
1878:
1879:            public void visitCastExpr(final CastExpr expr) {
1880:                expr.visitChildren(this );
1881:
1882:                genPostponed(expr);
1883:
1884:                if (expr.castType().isReference()) {
1885:                    method.addInstruction(Opcode.opcx_checkcast, expr
1886:                            .castType());
1887:                    return;
1888:                }
1889:
1890:                final int opType = expr.expr().type().typeCode();
1891:                final int castType = expr.castType().typeCode();
1892:
1893:                switch (opType) {
1894:                case Type.BYTE_CODE:
1895:                case Type.SHORT_CODE:
1896:                case Type.CHARACTER_CODE:
1897:                case Type.INTEGER_CODE:
1898:                    switch (castType) {
1899:                    case Type.BYTE_CODE:
1900:                        method.addInstruction(Opcode.opcx_i2b);
1901:                        return;
1902:                    case Type.SHORT_CODE:
1903:                        method.addInstruction(Opcode.opcx_i2s);
1904:                        return;
1905:                    case Type.CHARACTER_CODE:
1906:                        method.addInstruction(Opcode.opcx_i2c);
1907:                        return;
1908:                    case Type.INTEGER_CODE:
1909:                        return;
1910:                    case Type.LONG_CODE:
1911:                        method.addInstruction(Opcode.opcx_i2l);
1912:                        stackHeight += 1;
1913:                        return;
1914:                    case Type.FLOAT_CODE:
1915:                        method.addInstruction(Opcode.opcx_i2f);
1916:                        return;
1917:                    case Type.DOUBLE_CODE:
1918:                        method.addInstruction(Opcode.opcx_i2d);
1919:                        stackHeight += 1;
1920:                        return;
1921:                    }
1922:                    throw new IllegalArgumentException(
1923:                            "Can't generate cast for type "
1924:                                    + Type.getType(castType));
1925:                    // new Type(castType));
1926:
1927:                case Type.LONG_CODE:
1928:                    switch (castType) {
1929:                    case Type.BYTE_CODE:
1930:                        method.addInstruction(Opcode.opcx_l2i);
1931:                        stackHeight -= 1;
1932:                        method.addInstruction(Opcode.opcx_i2b);
1933:                        return;
1934:                    case Type.SHORT_CODE:
1935:                        method.addInstruction(Opcode.opcx_l2i);
1936:                        stackHeight -= 1;
1937:                        method.addInstruction(Opcode.opcx_i2s);
1938:                        return;
1939:                    case Type.CHARACTER_CODE:
1940:                        method.addInstruction(Opcode.opcx_l2i);
1941:                        stackHeight -= 1;
1942:                        method.addInstruction(Opcode.opcx_i2c);
1943:                        return;
1944:                    case Type.INTEGER_CODE:
1945:                        method.addInstruction(Opcode.opcx_l2i);
1946:                        stackHeight -= 1;
1947:                        return;
1948:                    case Type.LONG_CODE:
1949:                        return;
1950:                    case Type.FLOAT_CODE:
1951:                        method.addInstruction(Opcode.opcx_l2f);
1952:                        stackHeight -= 1;
1953:                        return;
1954:                    case Type.DOUBLE_CODE:
1955:                        method.addInstruction(Opcode.opcx_l2d);
1956:                        return;
1957:                    }
1958:
1959:                    throw new IllegalArgumentException(
1960:                            "Can't generate cast for type "
1961:                                    + Type.getType(castType));
1962:                    // new Type(castType));
1963:
1964:                case Type.FLOAT_CODE:
1965:                    switch (castType) {
1966:                    case Type.BYTE_CODE:
1967:                        method.addInstruction(Opcode.opcx_f2i);
1968:                        method.addInstruction(Opcode.opcx_i2b);
1969:                        return;
1970:                    case Type.SHORT_CODE:
1971:                        method.addInstruction(Opcode.opcx_f2i);
1972:                        method.addInstruction(Opcode.opcx_i2s);
1973:                        return;
1974:                    case Type.CHARACTER_CODE:
1975:                        method.addInstruction(Opcode.opcx_f2i);
1976:                        method.addInstruction(Opcode.opcx_i2c);
1977:                        return;
1978:                    case Type.INTEGER_CODE:
1979:                        method.addInstruction(Opcode.opcx_f2i);
1980:                        return;
1981:                    case Type.LONG_CODE:
1982:                        method.addInstruction(Opcode.opcx_f2l);
1983:                        stackHeight += 1;
1984:                        return;
1985:                    case Type.FLOAT_CODE:
1986:                        return;
1987:                    case Type.DOUBLE_CODE:
1988:                        method.addInstruction(Opcode.opcx_f2d);
1989:                        stackHeight += 1;
1990:                        return;
1991:                    }
1992:
1993:                    throw new IllegalArgumentException(
1994:                            "Can't generate cast for type "
1995:                                    + Type.getType(castType));
1996:                    // new Type(castType));
1997:
1998:                case Type.DOUBLE_CODE:
1999:                    switch (castType) {
2000:                    case Type.BYTE_CODE:
2001:                        method.addInstruction(Opcode.opcx_d2i);
2002:                        stackHeight -= 1;
2003:                        method.addInstruction(Opcode.opcx_i2b);
2004:                        return;
2005:                    case Type.SHORT_CODE:
2006:                        method.addInstruction(Opcode.opcx_d2i);
2007:                        stackHeight -= 1;
2008:                        method.addInstruction(Opcode.opcx_i2s);
2009:                        return;
2010:                    case Type.CHARACTER_CODE:
2011:                        method.addInstruction(Opcode.opcx_d2i);
2012:                        stackHeight -= 1;
2013:                        method.addInstruction(Opcode.opcx_i2c);
2014:                        return;
2015:                    case Type.INTEGER_CODE:
2016:                        method.addInstruction(Opcode.opcx_d2i);
2017:                        stackHeight -= 1;
2018:                        return;
2019:                    case Type.LONG_CODE:
2020:                        method.addInstruction(Opcode.opcx_d2l);
2021:                        return;
2022:                    case Type.FLOAT_CODE:
2023:                        method.addInstruction(Opcode.opcx_d2f);
2024:                        return;
2025:                    case Type.DOUBLE_CODE:
2026:                        return;
2027:                    }
2028:
2029:                    throw new IllegalArgumentException(
2030:                            "Can't generate cast for type "
2031:                                    + Type.getType(castType));
2032:                    // new Type(castType));
2033:                default:
2034:                    throw new IllegalArgumentException(
2035:                            "Can't generate cast from type "
2036:                                    + Type.getType(opType));
2037:                    // new Type(castType));
2038:                }
2039:            }
2040:
2041:            public void visitConstantExpr(final ConstantExpr expr) {
2042:                expr.visitChildren(this );
2043:
2044:                genPostponed(expr);
2045:
2046:                method.addInstruction(Opcode.opcx_ldc, expr.value());
2047:                stackHeight += expr.type().stackHeight();
2048:            }
2049:
2050:            public boolean nowb = false;
2051:
2052:            public void visitFieldExpr(final FieldExpr expr) {
2053:                expr.visitChildren(this );
2054:                genPostponed(expr);
2055:
2056:                if (expr.isDef()) {
2057:
2058:                    boolean UC = false; // Do we need an UC?
2059:
2060:                    // Look at the FieldExpr's object for a UCExpr
2061:                    Node check = expr.object();
2062:                    while (check instanceof  CheckExpr) {
2063:                        if (check instanceof  UCExpr) {
2064:                            UC = true;
2065:                            break;
2066:                        }
2067:
2068:                        final CheckExpr c = (CheckExpr) check;
2069:                        check = c.expr();
2070:                    }
2071:
2072:                    // Do we need to perform the write barrier?
2073:                    if (!UC && CodeGenerator.USE_PERSISTENT) {
2074:                        /*
2075:                         * System.out.println("Emitting a putfield_nowb in " +
2076:                         * this.method.declaringClass().classInfo().name() + "." +
2077:                         * this.method.name());
2078:                         */
2079:                        nowb = true;
2080:
2081:                        // I commented out the next line because it generated a compiler
2082:                        // error, and I figured it was just about some unimportant
2083:                        // persistance stuff --Tom
2084:                        // method.addInstruction(opcx_putfield_nowb, expr.field());
2085:
2086:                    } else {
2087:                        method.addInstruction(Opcode.opcx_putfield, expr
2088:                                .field());
2089:
2090:                    }
2091:
2092:                    stackHeight -= 1; // object
2093:                    stackHeight -= expr.type().stackHeight();
2094:
2095:                } else {
2096:                    method.addInstruction(Opcode.opcx_getfield, expr.field());
2097:                    stackHeight -= 1; // pop object
2098:                    stackHeight += expr.type().stackHeight();
2099:                }
2100:            }
2101:
2102:            public void visitInstanceOfExpr(final InstanceOfExpr expr) {
2103:                expr.visitChildren(this );
2104:                genPostponed(expr);
2105:                method.addInstruction(Opcode.opcx_instanceof , expr.checkType());
2106:            }
2107:
2108:            public void visitLocalExpr(final LocalExpr expr) {
2109:
2110:                genPostponed(expr);
2111:
2112:                final boolean cat2 = expr.type().isWide(); // how many stack positions
2113:                // does
2114:                // this take up?
2115:
2116:                int opcode = -1; // -1 is the flag that it hasn't yet been assigned
2117:                // a real value
2118:
2119:                if (CodeGenerator.DB_OPT_STACK) {
2120:                    currentSO.infoDisplay(expr);
2121:                }
2122:
2123:                if (expr.isDef()) {
2124:
2125:                    if (!CodeGenerator.OPT_STACK || currentSO.shouldStore(expr)) {
2126:
2127:                        if (expr.type().isAddress()) {
2128:                            opcode = Opcode.opcx_astore;
2129:                            stackHeight -= 1;
2130:                        } else if (expr.type().isReference()) {
2131:                            opcode = Opcode.opcx_astore;
2132:                            stackHeight -= 1;
2133:                        } else if (expr.type().isIntegral()) {
2134:                            opcode = Opcode.opcx_istore;
2135:                            stackHeight -= 1;
2136:                        } else if (expr.type().equals(Type.LONG)) {
2137:                            opcode = Opcode.opcx_lstore;
2138:                            stackHeight -= 2;
2139:                        } else if (expr.type().equals(Type.FLOAT)) {
2140:                            opcode = Opcode.opcx_fstore;
2141:                            stackHeight -= 1;
2142:                        } else if (expr.type().equals(Type.DOUBLE)) {
2143:                            opcode = Opcode.opcx_dstore;
2144:                            stackHeight -= 2;
2145:                        } else {
2146:                            throw new IllegalArgumentException(
2147:                                    "Can't generate code for type: "
2148:                                            + expr.type() + " (expr " + expr
2149:                                            + ")");
2150:                        }
2151:                    }
2152:                }
2153:
2154:                else {
2155:
2156:                    if (CodeGenerator.OPT_STACK && currentSO.onStack(expr)) { // don't
2157:                        // load
2158:                        // if
2159:                        // it's
2160:                        // already
2161:                        // on
2162:                        // the stack
2163:                        if (currentSO.shouldSwap(expr)) {
2164:                            if (cat2) {
2165:                                throw new IllegalArgumentException(
2166:                                        "Can't swap for wide expression "
2167:                                                + expr.toString() + " of type "
2168:                                                + expr.type().toString());
2169:                            } else {
2170:                                opcode = Opcode.opc_swap;
2171:                                stackHeight -= 1;
2172:                            }
2173:                        }
2174:                    } else {
2175:
2176:                        if (expr.type().isReference()) {
2177:                            opcode = Opcode.opcx_aload;
2178:                            stackHeight += 1;
2179:                        } else if (expr.type().isIntegral()) {
2180:                            opcode = Opcode.opcx_iload;
2181:                            stackHeight += 1;
2182:                        } else if (expr.type().equals(Type.LONG)) {
2183:                            opcode = Opcode.opcx_lload;
2184:                            stackHeight += 2;
2185:                        } else if (expr.type().equals(Type.FLOAT)) {
2186:                            opcode = Opcode.opcx_fload;
2187:                            stackHeight += 1;
2188:                        } else if (expr.type().equals(Type.DOUBLE)) {
2189:                            opcode = Opcode.opcx_dload;
2190:                            stackHeight += 2;
2191:                        } else {
2192:                            throw new IllegalArgumentException(
2193:                                    "Can't generate code for type: "
2194:                                            + expr.type() + " (expr " + expr
2195:                                            + ")");
2196:                        }
2197:                    }
2198:                }
2199:
2200:                if (opcode == Opcode.opc_swap) {
2201:                    method.addInstruction(opcode); // don't give
2202:                } else if ((opcode != -1) && !(expr.isDef())) { // if this is a load, we
2203:                    // want
2204:                    // the load before any dups.
2205:                    method.addInstruction(opcode, new LocalVariable(expr
2206:                            .index()));
2207:
2208:                    if (MethodEditor.OPT_STACK_2) {
2209:                        method.rememberDef(expr);
2210:                    }
2211:
2212:                }
2213:
2214:                if (CodeGenerator.OPT_STACK) {
2215:                    // generate dups for this value on top of the stack
2216:                    int dups, dup_x1s, dup_x2s;
2217:                    dups = currentSO.dups(expr);
2218:                    dup_x1s = currentSO.dup_x1s(expr);
2219:                    dup_x2s = currentSO.dup_x2s(expr);
2220:
2221:                    for (int i = 0; i < dup_x2s; i++) {
2222:                        if (cat2) { // (cat2 is for wide types)
2223:                            method.addInstruction(Opcode.opc_dup2_x2);
2224:                            stackHeight += 2;
2225:                        } else {
2226:                            method.addInstruction(Opcode.opc_dup_x2);
2227:                            stackHeight += 1;
2228:                        }
2229:                    }
2230:                    for (int i = 0; i < dup_x1s; i++) {
2231:                        if (cat2) {
2232:                            method.addInstruction(Opcode.opc_dup2_x1);
2233:                            stackHeight += 2;
2234:                        } else {
2235:                            method.addInstruction(Opcode.opc_dup_x1);
2236:                            stackHeight += 1;
2237:                        }
2238:                    }
2239:                    for (int i = 0; i < dups; i++) {
2240:                        if (cat2) {
2241:                            method.addInstruction(Opcode.opc_dup2);
2242:                            stackHeight += 2;
2243:                        } else {
2244:                            method.addInstruction(Opcode.opc_dup);
2245:                            stackHeight += 1;
2246:                        }
2247:                    }
2248:                }
2249:
2250:                // if we have an opcode for a def (i.e., a store), generate it
2251:                if ((opcode != -1) && expr.isDef()) {
2252:                    method.addInstruction(opcode, new LocalVariable(expr
2253:                            .index()));
2254:
2255:                    if (MethodEditor.OPT_STACK_2) {
2256:                        method.rememberDef(expr);
2257:                    }
2258:
2259:                }
2260:
2261:                if (CodeGenerator.OPT_STACK // if we shouldn't store,
2262:                        && !currentSO.shouldStore(expr)) { // an extra thing will be
2263:                    if (cat2) { // on the stack. pop it
2264:                        method.addInstruction(Opcode.opc_pop2);
2265:                        stackHeight -= 2;
2266:                    } else {
2267:                        method.addInstruction(Opcode.opc_pop);
2268:                        stackHeight -= 1;
2269:                    }
2270:                }
2271:                // (if this leaves a useless dup/pop combination, let peephole fix it)
2272:
2273:                // method.addInstruction(opcode, new LocalVariable(expr.index()));
2274:            }
2275:
2276:            public void visitNegExpr(final NegExpr expr) {
2277:                expr.visitChildren(this );
2278:
2279:                genPostponed(expr);
2280:
2281:                if (expr.type().isIntegral()) {
2282:                    method.addInstruction(Opcode.opcx_ineg);
2283:                } else if (expr.type().equals(Type.FLOAT)) {
2284:                    method.addInstruction(Opcode.opcx_fneg);
2285:                } else if (expr.type().equals(Type.LONG)) {
2286:                    method.addInstruction(Opcode.opcx_lneg);
2287:                } else if (expr.type().equals(Type.DOUBLE)) {
2288:                    method.addInstruction(Opcode.opcx_dneg);
2289:                } else {
2290:                    throw new IllegalArgumentException(
2291:                            "Can't generate code for type: " + expr.type()
2292:                                    + " (expr " + expr + ")");
2293:                }
2294:            }
2295:
2296:            public void visitNewArrayExpr(final NewArrayExpr expr) {
2297:                expr.visitChildren(this );
2298:
2299:                genPostponed(expr);
2300:
2301:                method.addInstruction(Opcode.opcx_newarray, expr.elementType());
2302:            }
2303:
2304:            public void visitNewExpr(final NewExpr expr) {
2305:                expr.visitChildren(this );
2306:
2307:                genPostponed(expr);
2308:
2309:                method.addInstruction(Opcode.opcx_new, expr.objectType());
2310:                stackHeight += 1;
2311:            }
2312:
2313:            public void visitNewMultiArrayExpr(final NewMultiArrayExpr expr) {
2314:                expr.visitChildren(this );
2315:
2316:                genPostponed(expr);
2317:
2318:                method.addInstruction(Opcode.opcx_multianewarray,
2319:                        new MultiArrayOperand(expr.elementType().arrayType(
2320:                                expr.dimensions().length),
2321:                                expr.dimensions().length));
2322:                stackHeight -= expr.dimensions().length;
2323:                stackHeight += 1;
2324:            }
2325:
2326:            public void visitReturnAddressExpr(final ReturnAddressExpr expr) {
2327:                genPostponed(expr);
2328:            }
2329:
2330:            public void visitShiftExpr(final ShiftExpr expr) {
2331:                expr.visitChildren(this );
2332:
2333:                genPostponed(expr);
2334:
2335:                if (expr.type().isIntegral()) {
2336:                    if (expr.dir() == ShiftExpr.LEFT) {
2337:                        method.addInstruction(Opcode.opcx_ishl);
2338:                        stackHeight -= 1;
2339:                    } else if (expr.dir() == ShiftExpr.RIGHT) {
2340:                        method.addInstruction(Opcode.opcx_ishr);
2341:                        stackHeight -= 1;
2342:                    } else {
2343:                        method.addInstruction(Opcode.opcx_iushr);
2344:                        stackHeight -= 1;
2345:                    }
2346:                } else if (expr.type().equals(Type.LONG)) {
2347:                    if (expr.dir() == ShiftExpr.LEFT) {
2348:                        method.addInstruction(Opcode.opcx_lshl);
2349:                        stackHeight -= 1;
2350:                    } else if (expr.dir() == ShiftExpr.RIGHT) {
2351:                        method.addInstruction(Opcode.opcx_lshr);
2352:                        stackHeight -= 1;
2353:                    } else {
2354:                        method.addInstruction(Opcode.opcx_lushr);
2355:                        stackHeight -= 1;
2356:                    }
2357:                } else {
2358:                    throw new IllegalArgumentException(
2359:                            "Can't generate code for type: " + expr.type()
2360:                                    + " (expr " + expr + ")");
2361:                }
2362:            }
2363:
2364:            public void visitDefExpr(final DefExpr expr) {
2365:                expr.visitChildren(this );
2366:                genPostponed(expr);
2367:            }
2368:
2369:            public void visitCatchExpr(final CatchExpr expr) {
2370:                expr.visitChildren(this );
2371:                genPostponed(expr);
2372:            }
2373:
2374:            public void visitStackExpr(final StackExpr expr) {
2375:                expr.visitChildren(this );
2376:                genPostponed(expr);
2377:            }
2378:
2379:            public void visitStaticFieldExpr(final StaticFieldExpr expr) {
2380:                expr.visitChildren(this );
2381:                genPostponed(expr);
2382:
2383:                if (expr.isDef()) {
2384:                    method.addInstruction(Opcode.opcx_putstatic, expr.field());
2385:                    stackHeight -= expr.type().stackHeight();
2386:                } else {
2387:                    method.addInstruction(Opcode.opcx_getstatic, expr.field());
2388:                    stackHeight += expr.type().stackHeight();
2389:                }
2390:            }
2391:
2392:            public void visitZeroCheckExpr(final ZeroCheckExpr expr) {
2393:                expr.visitChildren(this );
2394:                genPostponed(expr);
2395:            }
2396:
2397:            private void genPostponed(final Node node) {
2398:                final Instruction inst = (Instruction) postponedInstructions
2399:                        .get(node);
2400:
2401:                if (inst != null) {
2402:                    method.addInstruction(inst);
2403:                    // Luckily, the rc and aupdate don't change the stack!
2404:                    postponedInstructions.remove(node);
2405:                }
2406:            }
2407:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.