KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jode > flow > CreateNewConstructor


1 /* CreateNewConstructor 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: CreateNewConstructor.java,v 3.19.2.1 2002/05/28 17:34:09 hoenicke Exp $
18  */

19
20 package jode.flow;
21 import jode.expr.*;
22 import jode.bytecode.Reference;
23 import jode.decompiler.MethodAnalyzer;
24 import jode.type.Type;
25
26 public class CreateNewConstructor {
27
28     public static boolean transform(InstructionContainer ic,
29                                     StructuredBlock last) {
30     return transformNormal(ic, last) || transformJikesString(ic, last);
31     }
32
33     static boolean transformJikesString(InstructionContainer ic,
34                     StructuredBlock last) {
35         /* special Situation for Jikes String +=:
36          *
37      * PUSH new StringBuffer()
38      * SWAP
39      * PUSH POP.append(POP)
40          *
41          * We transform it to the javac String +=:
42      *
43      * PUSH new StringBuffer(String.valueOf(POP))
44      */

45         if (!(last.outer instanceof SequentialBlock)
46         || !(ic.getInstruction() instanceof InvokeOperator))
47             return false;
48
49         InvokeOperator appendCall = (InvokeOperator) ic.getInstruction();
50         if (!appendCall.getClassType().equals(Type.tStringBuffer)
51         || !appendCall.isFreeOperator(2)
52             || appendCall.isStatic()
53             || !appendCall.getMethodName().equals("append")
54             || appendCall.getMethodType().getParameterTypes().length != 1)
55         return false;
56
57     SequentialBlock sequBlock = (SequentialBlock) last.outer;
58     if (!(sequBlock.outer instanceof SequentialBlock)
59         || !(sequBlock.subBlocks[0] instanceof SpecialBlock))
60         return false;
61
62     SpecialBlock swapBlock = (SpecialBlock) sequBlock.subBlocks[0];
63     sequBlock = (SequentialBlock) sequBlock.outer;
64     if (swapBlock.type != SpecialBlock.SWAP
65         || !(sequBlock.subBlocks[0] instanceof InstructionBlock)
66         || !(sequBlock.outer instanceof SequentialBlock))
67         return false;
68
69     InstructionBlock ib = (InstructionBlock) sequBlock.subBlocks[0];
70     sequBlock = (SequentialBlock) sequBlock.outer;
71     if (!(ib.getInstruction() instanceof InvokeOperator)
72         || !(sequBlock.subBlocks[0] instanceof InstructionBlock))
73         return false;
74
75     InvokeOperator constr = (InvokeOperator) ib.getInstruction();
76     ib = (InstructionBlock) sequBlock.subBlocks[0];
77
78     if (!constr.isConstructor()
79         || !constr.getClassType().equals(Type.tStringBuffer)
80         || constr.isVoid()
81         || constr.getMethodType().getParameterTypes().length != 0)
82         return false;
83
84     /* Okay everything checked. */
85     MethodAnalyzer methodAna = ib.flowBlock.method;
86     Expression expr = ib.getInstruction();
87     Type appendType = appendCall.getMethodType().getParameterTypes()[0];
88     if (!appendType.equals(Type.tString)) {
89         InvokeOperator valueOf = new InvokeOperator
90         (methodAna, InvokeOperator.STATIC,
91          Reference.getReference("Ljava/lang/String;", "valueOf",
92                     "(" + appendType.getTypeSignature()
93                     + ")Ljava/lang/String;"));
94         expr = valueOf.addOperand(expr);
95     }
96     InvokeOperator newConstr = new InvokeOperator
97         (methodAna, InvokeOperator.CONSTRUCTOR,
98          Reference.getReference("Ljava/lang/StringBuffer;", "<init>",
99                     "(Ljava/lang/String;)V"));
100     newConstr.makeNonVoid();
101     newConstr.setSubExpressions(0, constr.getSubExpressions()[0]);
102     newConstr.setSubExpressions(1, expr);
103     ic.setInstruction(newConstr);
104     last.replace(sequBlock);
105     return true;
106     }
107
108     static boolean transformNormal(InstructionContainer ic,
109                    StructuredBlock last) {
110         /* Situation (normal):
111      *
112          * new <object>
113          * (optional DUP)
114      * (void resolved expressions)
115          * stack_n.<init>(resolved expressions)
116          *
117          * transform it to
118          *
119      * (void resolved expressions)
120          * (optional PUSH) new <object>((optional: stack_n),
121      * resolved expressions)
122      *
123      * special situation for string1 += string2:
124      *
125          * new <object>
126          * (optional DUP)
127      * (void resolved expressions)
128          * PUSH load_ops
129          * DUP_X2/1 <= 2 if above DUP is present
130          * stack_n.<init>(stack_n, resolved expressions)
131          *
132          * transform it to
133          *
134      * (void resolved expressions)
135          * PUSH load_ops
136          * DUP <= remove the depth
137          * (optional PUSH) new <object>(stack_n, resolved expressions)
138          */

139
140         if (!(last.outer instanceof SequentialBlock))
141             return false;
142         if (!(ic.getInstruction() instanceof InvokeOperator))
143             return false;
144         InvokeOperator constrCall = (InvokeOperator) ic.getInstruction();
145         if (!constrCall.isConstructor() || !constrCall.isVoid())
146             return false;
147
148         /* The rest should probably succeed */
149
150         SpecialBlock optDupX2 = null;
151         SequentialBlock sequBlock = (SequentialBlock) last.outer;
152     Expression[] subs = constrCall.getSubExpressions();
153     int opcount = constrCall.getFreeOperandCount();
154     if (subs != null) {
155         if (!(subs[0] instanceof NopOperator))
156         return false;
157         if (constrCall.getFreeOperandCount() > 1) {
158         if (!(sequBlock.outer instanceof SequentialBlock)
159             || !(sequBlock.subBlocks[0] instanceof SpecialBlock))
160             return false;
161         optDupX2 = (SpecialBlock) sequBlock.subBlocks[0];
162         sequBlock = (SequentialBlock) sequBlock.outer;
163         if (optDupX2.type != SpecialBlock.DUP
164             || optDupX2.depth == 0)
165             return false;
166         int count = optDupX2.count;
167         do {
168             if (!(sequBlock.outer instanceof SequentialBlock)
169             || !(sequBlock.subBlocks[0]
170                  instanceof InstructionBlock))
171             return false;
172             Expression expr =
173             ((InstructionBlock)
174              sequBlock.subBlocks[0]).getInstruction();
175             sequBlock = (SequentialBlock) sequBlock.outer;
176
177             if (expr.isVoid())
178             continue;
179             count -= expr.getType().stackSize();
180             opcount--;
181         } while (count > 0 && opcount > 1);
182         if (count != 0)
183             return false;
184         }
185     }
186     if (opcount != 1)
187         return false;
188     
189     while (sequBlock.subBlocks[0] instanceof InstructionBlock
190            && sequBlock.outer instanceof SequentialBlock) {
191         Expression expr
192         = ((InstructionBlock)sequBlock.subBlocks[0]).getInstruction();
193         if (!expr.isVoid() || expr.getFreeOperandCount() > 0)
194         break;
195             sequBlock = (SequentialBlock) sequBlock.outer;
196     }
197                
198         SpecialBlock dup = null;
199         if (sequBlock.outer instanceof SequentialBlock
200             && sequBlock.subBlocks[0] instanceof SpecialBlock) {
201
202             dup = (SpecialBlock) sequBlock.subBlocks[0];
203             if (dup.type != SpecialBlock.DUP
204                 || dup.count != 1 || dup.depth != 0)
205                 return false;
206             sequBlock = (SequentialBlock)sequBlock.outer;
207         if (optDupX2 != null && optDupX2.depth != 2)
208         return false;
209         } else if (optDupX2 != null && optDupX2.depth != 1)
210         return false;
211
212         if (!(sequBlock.subBlocks[0] instanceof InstructionBlock))
213             return false;
214         InstructionBlock block = (InstructionBlock) sequBlock.subBlocks[0];
215         if (!(block.getInstruction() instanceof NewOperator))
216             return false;
217         
218         NewOperator op = (NewOperator) block.getInstruction();
219         if (constrCall.getClassType() != op.getType())
220             return false;
221         
222         block.removeBlock();
223         if (dup != null)
224             dup.removeBlock();
225         if (optDupX2 != null)
226             optDupX2.depth = 0;
227
228     constrCall.setSubExpressions(0, op);
229     if (dup != null)
230         constrCall.makeNonVoid();
231 // Expression newExpr = new ConstructorOperator
232
// (constrCall, dup == null);
233

234 // if (subs != null) {
235
// for (int i=subs.length; i-- > 1; )
236
// newExpr = newExpr.addOperand(subs[i]);
237
// }
238
// ic.setInstruction(newExpr);
239
return true;
240     }
241 }
242
Popular Tags