KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jode > flow > SpecialBlock


1 /* SpecialBlock Copyright (C) 1998-2002 Jochen Hoenicke.
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU Lesser General Public License as published by
5  * the Free Software Foundation; either version 2, or (at your option)
6  * any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this program; see the file COPYING.LESSER. If not, write to
15  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
16  *
17  * $Id: SpecialBlock.java,v 1.15.2.2 2002/05/28 17:34:09 hoenicke Exp $
18  */

19
20 package jode.flow;
21 import jode.decompiler.TabbedPrintWriter;
22 import jode.expr.*;
23
24 /**
25  * This is the structured block for atomic instructions.
26  */

27 public class SpecialBlock extends StructuredBlock {
28
29     public static int DUP = 0;
30     public static int SWAP = 1;
31     public static int POP = 2;
32     private static String JavaDoc[] output = { "DUP", "SWAP", "POP" };
33
34     /**
35      * The type, one of DUP or SWAP
36      */

37     int type;
38     /**
39      * The count of stack entries that are transformed.
40      * This is 1 for swap, and 1 or 2 for dup.
41      */

42     int count;
43     /**
44      * The depth that the dupped element should be put to (0,1 or 2).
45      * For swap this is zero.
46      */

47     int depth;
48
49     public SpecialBlock(int type, int count, int depth, Jump jump) {
50         this.type = type;
51         this.count = count;
52         this.depth = depth;
53     setJump(jump);
54     }
55
56     /**
57      * This does take the instr into account and modifies stack
58      * accordingly. It then calls super.mapStackToLocal.
59      * @param stack the stack before the instruction is called
60      * @return stack the stack afterwards.
61      */

62     public VariableStack mapStackToLocal(VariableStack stack) {
63     /* a SpecialBlock is special :-) */
64     VariableStack after = stack.executeSpecial(this);
65     return super.mapStackToLocal(after);
66     }
67
68     public void removePush() {
69     /* XXX */
70     removeBlock();
71     }
72
73
74     public void dumpInstruction(TabbedPrintWriter writer)
75     throws java.io.IOException JavaDoc
76     {
77     writer.println(output[type]
78                + ((count == 1) ? "" : "2")
79                + ((depth == 0) ? "" : "_X"+depth));
80     }
81
82     public boolean doTransformations() {
83         return (type == SWAP && removeSwap(flowBlock.lastModified))
84         || (type == POP && removePop(flowBlock.lastModified));
85     }
86
87     public boolean removeSwap(StructuredBlock last) {
88
89         /* Remove non needed swaps; convert:
90          *
91          * PUSH expr1
92          * PUSH expr2
93          * SWAP
94          *
95          * to:
96          *
97          * PUSH expr2
98          * PUSH expr1
99          */

100         if (last.outer instanceof SequentialBlock
101             && last.outer.outer instanceof SequentialBlock
102             && last.outer.getSubBlocks()[0] instanceof InstructionBlock
103             && last.outer.outer.getSubBlocks()[0]
104             instanceof InstructionBlock) {
105
106             InstructionBlock block1
107                 = (InstructionBlock) last.outer.outer.getSubBlocks()[0];
108             InstructionBlock block2
109                 = (InstructionBlock) last.outer.getSubBlocks()[0];
110
111         Expression expr1 = block1.getInstruction();
112         Expression expr2 = block2.getInstruction();
113
114             if (expr1.isVoid() || expr2.isVoid()
115         || expr1.getFreeOperandCount() != 0
116         || expr2.getFreeOperandCount() != 0
117         || expr1.hasSideEffects(expr2)
118         || expr2.hasSideEffects(expr1))
119                 return false;
120
121             /* PUSH expr1 == block1
122              * PUSH expr2
123              * SWAP
124              * ...
125              */

126             last.outer.replace(block1.outer);
127             /* PUSH expr2
128              * SWAP
129              * ...
130              */

131             block1.replace(this);
132             block1.moveJump(jump);
133             /* PUSH expr2
134              * PUSH expr1
135              */

136             block1.flowBlock.lastModified = block1;
137             return true;
138         }
139         return false;
140     }
141
142     public boolean removePop(StructuredBlock last) {
143
144     /* There are three possibilities:
145          *
146          * PUSH method_invocation()
147          * POP[sizeof PUSH]
148          * to:
149          * method_invocation()
150      *
151      * With java1.3 due to access$ methods the method_invocation can
152      * already be a non void store instruction.
153      *
154      * PUSH arg1
155      * PUSH arg2
156      * POP2
157      * to:
158      * if (arg1 == arg2)
159      * empty
160      *
161      * PUSH arg1
162      * POP
163      * to:
164      * if (arg1 != 0)
165      * empty
166          */

167
168         if (last.outer instanceof SequentialBlock
169         && last.outer.getSubBlocks()[0] instanceof InstructionBlock) {
170
171         if (jump != null && jump.destination == null)
172         return false;
173
174             InstructionBlock prev
175                 = (InstructionBlock) last.outer.getSubBlocks()[0];
176         Expression instr = prev.getInstruction();
177
178         if (instr.getType().stackSize() == count) {
179         StructuredBlock newBlock;
180         if (instr instanceof InvokeOperator
181             || instr instanceof StoreInstruction) {
182             Expression newExpr
183             = new PopOperator(instr.getType()).addOperand(instr);
184             prev.setInstruction(newExpr);
185             newBlock = prev;
186         } else {
187             Expression newCond = new CompareUnaryOperator
188             (instr.getType(), Operator.NOTEQUALS_OP)
189             .addOperand(instr);
190             IfThenElseBlock newIfThen = new IfThenElseBlock(newCond);
191             newIfThen.setThenBlock(new EmptyBlock());
192             newBlock = newIfThen;
193         }
194         // We don't move the definitions of the special block, but
195
// it shouldn't have any.
196
newBlock.moveDefinitions(last.outer, last);
197         newBlock.moveJump(jump);
198         if (this == last) {
199             newBlock.replace(last.outer);
200             flowBlock.lastModified = newBlock;
201         } else {
202             newBlock.replace(this);
203             last.replace(last.outer);
204         }
205         return true;
206         }
207         }
208         return false;
209     }
210 }
211
Popular Tags