KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jode > flow > TryBlock


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

19
20 package jode.flow;
21 import jode.decompiler.TabbedPrintWriter;
22 import jode.type.*;
23 import jode.expr.Expression;
24 import jode.expr.InvokeOperator;
25 import jode.expr.LocalLoadOperator;
26
27 /**
28  * A TryBlock is created for each exception in the
29  * ExceptionHandlers-Attribute. <p>
30  *
31  * For each catch block (there may be more than one catch block
32  * appending a single try block) and for each finally and each
33  * synchronized block such a TryBlock is created. The
34  * finally/synchronized-blocks have a null exception type so that they
35  * are easily distinguishable from the catch blocks. <p>
36  *
37  * A TryBlock is an intermediate representation that gets
38  * converted later to a CatchBlock, a FinallyBlock or a
39  * SynchronizedBlock (after the body is parsed).
40  *
41  * @date 1998/09/16
42  * @author Jochen Hoenicke
43  * @see CatchBlock
44  * @see FinallyBlock
45  * @see SynchronizedBlock
46  */

47
48 public class TryBlock extends StructuredBlock {
49
50     VariableSet gen;
51     StructuredBlock[] subBlocks = new StructuredBlock[1];
52
53     public TryBlock(FlowBlock tryFlow) {
54         this.gen = (VariableSet) tryFlow.gen.clone();
55         this.flowBlock = tryFlow;
56
57         StructuredBlock bodyBlock = tryFlow.block;
58         replace(bodyBlock);
59         this.subBlocks = new StructuredBlock[] { bodyBlock };
60         bodyBlock.outer = this;
61         tryFlow.lastModified = this;
62     tryFlow.checkConsistent();
63     }
64
65     public void addCatchBlock(StructuredBlock catchBlock) {
66         StructuredBlock[] newSubBlocks =
67             new StructuredBlock[subBlocks.length+1];
68         System.arraycopy(subBlocks, 0, newSubBlocks, 0, subBlocks.length);
69         newSubBlocks[subBlocks.length] = catchBlock;
70         subBlocks = newSubBlocks;
71         catchBlock.outer = this;
72         catchBlock.setFlowBlock(flowBlock);
73     }
74
75     /**
76      * Replaces the given sub block with a new block.
77      * @param oldBlock the old sub block.
78      * @param newBlock the new sub block.
79      * @return false, if oldBlock wasn't a direct sub block.
80      */

81     public boolean replaceSubBlock(StructuredBlock oldBlock,
82                                    StructuredBlock newBlock) {
83         for (int i=0; i<subBlocks.length; i++) {
84             if (subBlocks[i] == oldBlock) {
85                 subBlocks[i] = newBlock;
86                 return true;
87             }
88         }
89         return false;
90     }
91
92     /**
93      * Returns all sub block of this structured block.
94      */

95     public StructuredBlock[] getSubBlocks() {
96         return subBlocks;
97     }
98
99     /**
100      * This does take the instr into account and modifies stack
101      * accordingly. It then calls super.mapStackToLocal.
102      * @param stack the stack before the instruction is called
103      * @return stack the stack afterwards.
104      */

105     public VariableStack mapStackToLocal(VariableStack stack) {
106     // first the try block.
107
VariableStack after = subBlocks[0].mapStackToLocal(stack);
108     for (int i = 1; i<subBlocks.length; i++) {
109         // now merge the catch blocks; they start on empty stack.
110
after = VariableStack.merge
111         (after, subBlocks[i].mapStackToLocal(VariableStack.EMPTY));
112     }
113     if (jump != null) {
114         jump.stackMap = after;
115         return null;
116     }
117     return after;
118     }
119
120     public void dumpInstruction(TabbedPrintWriter writer)
121         throws java.io.IOException JavaDoc {
122         writer.print("try");
123     writer.openBrace();
124         writer.tab();
125         subBlocks[0].dumpSource(writer);
126         writer.untab();
127         for (int i=1; i<subBlocks.length;i++)
128             subBlocks[i].dumpSource(writer);
129     writer.closeBrace();
130     }
131
132     /**
133      * Determines if there is a sub block, that flows through to the end
134      * of this block. If this returns true, you know that jump is null.
135      * @return true, if the jump may be safely changed.
136      */

137     public boolean jumpMayBeChanged() {
138         for (int i=0; i<subBlocks.length;i++) {
139             if (subBlocks[i].jump == null
140                 && !subBlocks[i].jumpMayBeChanged())
141                 return false;
142         }
143         return true;
144     }
145
146     /**
147      * A special transformation for try blocks:
148      * jikes generate try/catch-blocks for array clone:
149      * <pre>
150      * try {
151      * PUSH ARRAY.clone()
152      * } catch (CloneNotSupportedException ex) {
153      * throw new InternalError(ex.getMessage());
154      * }
155      * </pre>
156      * which is simply transformed to the content of the try block.
157      */

158     public boolean checkJikesArrayClone() {
159
160     if (subBlocks.length != 2
161         || !(subBlocks[0] instanceof InstructionBlock)
162         || !(subBlocks[1] instanceof CatchBlock))
163         return false;
164
165     Expression instr =
166         ((InstructionBlock)subBlocks[0]).getInstruction();
167     CatchBlock catchBlock = (CatchBlock) subBlocks[1];
168
169     if (instr.isVoid() || instr.getFreeOperandCount() != 0
170         || !(instr instanceof InvokeOperator)
171         || !(catchBlock.catchBlock instanceof ThrowBlock)
172         || !(catchBlock.exceptionType.equals
173          (Type.tClass("java.lang.CloneNotSupportedException"))))
174         return false;
175
176     InvokeOperator arrayClone = (InvokeOperator) instr;
177     if (!arrayClone.getMethodName().equals("clone")
178         || arrayClone.isStatic()
179         || !(arrayClone.getMethodType().getTypeSignature()
180          .equals("()Ljava/lang/Object;"))
181         || !(arrayClone.getSubExpressions()[0]
182          .getType().isOfType(Type.tArray(Type.tUnknown))))
183         return false;
184     
185     Expression throwExpr =
186         ((ThrowBlock) catchBlock.catchBlock).getInstruction();
187     
188     if (throwExpr.getFreeOperandCount() != 0
189         || !(throwExpr instanceof InvokeOperator))
190         return false;
191     
192     InvokeOperator throwOp = (InvokeOperator) throwExpr;
193     if (!throwOp.isConstructor()
194         || !(throwOp.getClassType()
195          .equals(Type.tClass("java.lang.InternalError")))
196         || throwOp.getMethodType().getParameterTypes().length != 1)
197         return false;
198     
199     Expression getMethodExpr = throwOp.getSubExpressions()[1];
200     if (!(getMethodExpr instanceof InvokeOperator))
201         return false;
202
203     InvokeOperator invoke = (InvokeOperator) getMethodExpr;
204     if (!invoke.getMethodName().equals("getMessage")
205         || invoke.isStatic()
206         || (invoke.getMethodType().getParameterTypes()
207         .length != 0)
208         || (invoke.getMethodType().getReturnType()
209         != Type.tString))
210         return false;
211     
212     Expression exceptExpr = invoke.getSubExpressions()[0];
213     if (!(exceptExpr instanceof LocalLoadOperator)
214         || !(((LocalLoadOperator) exceptExpr).getLocalInfo()
215          .equals(catchBlock.exceptionLocal)))
216         return false;
217
218     subBlocks[0].replace(this);
219     if (flowBlock.lastModified == this)
220         flowBlock.lastModified = subBlocks[0];
221     return true;
222     }
223
224     public boolean doTransformations() {
225     return checkJikesArrayClone();
226     }
227 }
228
Popular Tags