History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/tools/tree/FinallyStatement.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/tools/tree/FinallyStatement.java+360−0
@@ -0,0 +1,360 @@
1+/*
2+ * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.tools.tree;
27+
28+import sun.tools.java.*;
29+import sun.tools.asm.Assembler;
30+import sun.tools.asm.Label;
31+import sun.tools.asm.TryData;
32+import sun.tools.asm.CatchData;
33+import java.io.PrintStream;
34+import java.util.Hashtable;
35+import java.util.Enumeration;
36+
37+/**
38+ * WARNING: The contents of this source file are not part of any
39+ * supported API. Code that depends on them does so at its own risk:
40+ * they are subject to change or removal without notice.
41+ */
42+public
43+class FinallyStatement extends Statement {
44+ Statement body;
45+ Statement finalbody;
46+ boolean finallyCanFinish; // does finalBody never return?
47+ boolean needReturnSlot; // set by inner return statement
48+ Statement init; // try object expression or declaration from parser
49+ LocalMember tryTemp; // temp holding the try object, if any
50+
51+ /**
52+ * Constructor
53+ */
54+ public FinallyStatement(long where, Statement body, Statement finalbody) {
55+ super(FINALLY, where);
56+ this.body = body;
57+ this.finalbody = finalbody;
58+ }
59+
60+// /**
61+// * Constructor for try (init) {body}
62+// */
63+// public FinallyStatement(long where, Statement init, Statement body, int junk) {
64+// this(where, body, null);
65+// this.init = init;
66+// }
67+
68+ /**
69+ * Check statement
70+ */
71+ Vset check(Environment env, Context ctx, Vset vset, Hashtable exp) {
72+ vset = reach(env, vset);
73+ Hashtable newexp = new Hashtable();
74+
75+ // Handle the proposed 'try (init) { stmts } finally { stmts }' syntax.
76+ // This feature has not been adopted, and support is presently disabled.
77+ /*-----------------------------------------------------------*
78+ if (init != null) {
79+ ClassDefinition sourceClass = ctx.field.getClassDefinition();
80+ Expression tryExpr = null;
81+ DeclarationStatement tryDecl = null;
82+ long where = init.getWhere();
83+ // find out whether init is a simple expression or a declaration
84+ if (init.getOp() == EXPRESSION) {
85+ tryExpr = ((ExpressionStatement)init).expr;
86+ init = null; // restore it below
87+ vset = tryExpr.checkValue(env, ctx, vset, exp);
88+ } else if (init.getOp() == DECLARATION) {
89+ tryDecl = (DeclarationStatement) init;
90+ init = null; // restore it below
91+ vset = tryDecl.checkBlockStatement(env, ctx, vset, exp);
92+ if (tryDecl.args.length != 1) {
93+ env.error(where, "invalid.decl");
94+ } else {
95+ LocalMember field =
96+ ((VarDeclarationStatement) tryDecl.args[0]).field;
97+ tryExpr = new IdentifierExpression(where, field);
98+ tryExpr.type = field.getType();
99+ }
100+ } else {
101+ env.error(where, "invalid.expr");
102+ vset = init.check(env, ctx, vset, exp);
103+ }
104+ Type type = (tryExpr == null) ? Type.tError : tryExpr.getType();
105+
106+ MemberDefinition tryEnter = null;
107+ MemberDefinition tryExit = null;
108+ if (!type.isType(TC_CLASS)) {
109+ if (!type.isType(TC_ERROR)) {
110+ env.error(where, "invalid.method.invoke", type);
111+ }
112+ } else {
113+ Identifier idTryEnter = Identifier.lookup("tryEnter");
114+ Identifier idTryExit = Identifier.lookup("tryExit");
115+ Type tTryMethod = Type.tMethod(Type.tVoid);
116+ try {
117+ ClassDefinition tryClass = env.getClassDefinition(type);
118+ tryEnter = tryClass.matchMethod(env, sourceClass, idTryEnter);
119+ tryExit = tryClass.matchMethod(env, sourceClass, idTryExit);
120+ if (tryEnter != null && !tryEnter.getType().equals(tTryMethod)) {
121+ tryEnter = null;
122+ }
123+ if (tryExit != null && !tryExit.getType().equals(tTryMethod)) {
124+ tryExit = null;
125+ }
126+ } catch (ClassNotFound ee) {
127+ env.error(where, "class.not.found", ee.name, ctx.field);
128+ } catch (AmbiguousMember ee) {
129+ Identifier id = ee.field1.getName();
130+ env.error(where, "ambig.field", id, ee.field1, ee.field2);
131+ }
132+ }
133+ if (tryEnter == null || tryExit == null) {
134+ // Make a better (more didactic) error here!
135+ env.error(where, "invalid.method.invoke", type);
136+ } else {
137+ tryTemp = new LocalMember(where, sourceClass, 0,
138+ type, Identifier.lookup("<try_object>"));
139+ ctx = new Context(ctx, this);
140+ ctx.declare(env, tryTemp);
141+
142+ Expression e;
143+ e = new IdentifierExpression(where, tryTemp);
144+ e = new AssignExpression(where, e, tryExpr);
145+ e = new MethodExpression(where, e, tryEnter, new Expression[0]);
146+ e.type = Type.tVoid;
147+ Statement enterCall = new ExpressionStatement(where, e);
148+ // store it on the init, for code generation
149+ if (tryDecl != null) {
150+ Statement args2[] = { tryDecl.args[0], enterCall };
151+ tryDecl.args = args2;
152+ init = tryDecl;
153+ } else {
154+ init = enterCall;
155+ }
156+ e = new IdentifierExpression(where, tryTemp);
157+ e = new MethodExpression(where, e, tryExit, new Expression[0]);
158+ e.type = Type.tVoid;
159+ Statement exitCall = new ExpressionStatement(where, e);
160+ finalbody = exitCall;
161+ }
162+ }
163+ *-----------------------------------------------------------*/
164+
165+ // Check the try part. We reach the end of the try part either by
166+ // finishing normally, or doing a break to the label of the try/finally.
167+ // NOTE: I don't think newctx1.vsBreak is ever used -- see TryStatement.
168+ CheckContext newctx1 = new CheckContext(ctx, this);
169+ Vset vset1 = body.check(env, newctx1, vset.copy(), newexp)
170+ .join(newctx1.vsBreak);
171+ // Check the finally part.
172+ CheckContext newctx2 = new CheckContext(ctx, this);
173+ // Should never access this field. The null indicates the finally part.
174+ newctx2.vsContinue = null;
175+ Vset vset2 = finalbody.check(env, newctx2, vset, exp);
176+ finallyCanFinish = !vset2.isDeadEnd();
177+ vset2 = vset2.join(newctx2.vsBreak);
178+ // If !finallyCanFinish, then the only possible exceptions that can
179+ // occur at this point are the ones preceding the try/finally, or
180+ // the ones generated by the finally. Anything in the try is
181+ // irrelevant. Otherwise, we have to merge in all the exceptions
182+ // generated by the body into exp.
183+ if (finallyCanFinish) {
184+ // Add newexp's back into exp; cf. ThrowStatement.check().
185+ for (Enumeration e = newexp.keys() ; e.hasMoreElements() ; ) {
186+ Object def = e.nextElement();
187+ exp.put(def, newexp.get(def));
188+ }
189+ }
190+ return ctx.removeAdditionalVars(vset1.addDAandJoinDU(vset2));
191+ }
192+
193+ /**
194+ * Inline
195+ */
196+ public Statement inline(Environment env, Context ctx) {
197+ if (tryTemp != null) {
198+ ctx = new Context(ctx, this);
199+ ctx.declare(env, tryTemp);
200+ }
201+ if (init != null) {
202+ init = init.inline(env, ctx);
203+ }
204+ if (body != null) {
205+ body = body.inline(env, ctx);
206+ }
207+ if (finalbody != null) {
208+ finalbody = finalbody.inline(env, ctx);
209+ }
210+ if (body == null) {
211+ return eliminate(env, finalbody);
212+ }
213+ if (finalbody == null) {
214+ return eliminate(env, body);
215+ }
216+ return this;
217+ }
218+
219+ /**
220+ * Create a copy of the statement for method inlining
221+ */
222+ public Statement copyInline(Context ctx, boolean valNeeded) {
223+ FinallyStatement s = (FinallyStatement)clone();
224+ if (tryTemp != null) {
225+ s.tryTemp = tryTemp.copyInline(ctx);
226+ }
227+ if (init != null) {
228+ s.init = init.copyInline(ctx, valNeeded);
229+ }
230+ if (body != null) {
231+ s.body = body.copyInline(ctx, valNeeded);
232+ }
233+ if (finalbody != null) {
234+ s.finalbody = finalbody.copyInline(ctx, valNeeded);
235+ }
236+ return s;
237+ }
238+
239+ /**
240+ * Compute cost of inlining this statement
241+ */
242+ public int costInline(int thresh, Environment env, Context ctx){
243+ int cost = 4;
244+ if (init != null) {
245+ cost += init.costInline(thresh, env,ctx);
246+ if (cost >= thresh) return cost;
247+ }
248+ if (body != null) {
249+ cost += body.costInline(thresh, env,ctx);
250+ if (cost >= thresh) return cost;
251+ }
252+ if (finalbody != null) {
253+ cost += finalbody.costInline(thresh, env,ctx);
254+ }
255+ return cost;
256+ }
257+
258+ /**
259+ * Code
260+ */
261+ public void code(Environment env, Context ctx, Assembler asm) {
262+ ctx = new Context(ctx);
263+ Integer num1 = null, num2 = null;
264+ Label endLabel = new Label();
265+
266+ if (tryTemp != null) {
267+ ctx.declare(env, tryTemp);
268+ }
269+ if (init != null) {
270+ CodeContext exprctx = new CodeContext(ctx, this);
271+ init.code(env, exprctx, asm);
272+ }
273+
274+ if (finallyCanFinish) {
275+ LocalMember f1, f2;
276+ ClassDefinition thisClass = ctx.field.getClassDefinition();
277+
278+ if (needReturnSlot) {
279+ Type returnType = ctx.field.getType().getReturnType();
280+ LocalMember localfield = new LocalMember(0, thisClass, 0,
281+ returnType,
282+ idFinallyReturnValue);
283+ ctx.declare(env, localfield);
284+ env.debugOutput("Assigning return slot to " + localfield.number);
285+ }
286+
287+ // allocate space for the exception and return address
288+ f1 = new LocalMember(where, thisClass, 0, Type.tObject, null);
289+ f2 = new LocalMember(where, thisClass, 0, Type.tInt, null);
290+ num1 = new Integer(ctx.declare(env, f1));
291+ num2 = new Integer(ctx.declare(env, f2));
292+ }
293+
294+ TryData td = new TryData();
295+ td.add(null);
296+
297+ // Main body
298+ CodeContext bodyctx = new CodeContext(ctx, this);
299+ asm.add(where, opc_try, td); // start of protected code
300+ body.code(env, bodyctx, asm);
301+ asm.add(bodyctx.breakLabel);
302+ asm.add(td.getEndLabel()); // end of protected code
303+
304+ // Cleanup afer body
305+ if (finallyCanFinish) {
306+ asm.add(where, opc_jsr, bodyctx.contLabel);
307+ asm.add(where, opc_goto, endLabel);
308+ } else {
309+ // just goto the cleanup code. It will never return.
310+ asm.add(where, opc_goto, bodyctx.contLabel);
311+ }
312+
313+ // Catch code
314+ CatchData cd = td.getCatch(0);
315+ asm.add(cd.getLabel());
316+ if (finallyCanFinish) {
317+ asm.add(where, opc_astore, num1); // store exception
318+ asm.add(where, opc_jsr, bodyctx.contLabel);
319+ asm.add(where, opc_aload, num1); // rethrow exception
320+ asm.add(where, opc_athrow);
321+ } else {
322+ // pop exception off stack. Fall through to finally code
323+ asm.add(where, opc_pop);
324+ }
325+
326+ // The finally part, which is marked by the contLabel. Update
327+ // breakLabel: since break's in the finally are different
328+ // contLabel: to null to indicate no longer in the protected code.
329+ asm.add(bodyctx.contLabel);
330+ bodyctx.contLabel = null;
331+ bodyctx.breakLabel = endLabel;
332+ if (finallyCanFinish) {
333+ asm.add(where, opc_astore, num2); // save the return address
334+ finalbody.code(env, bodyctx, asm); // execute the cleanup code
335+ asm.add(where, opc_ret, num2); // return
336+ } else {
337+ finalbody.code(env, bodyctx, asm); // execute the cleanup code
338+ }
339+ asm.add(endLabel); // breaks come here
340+ }
341+
342+ /**
343+ * Print
344+ */
345+ public void print(PrintStream out, int indent) {
346+ super.print(out, indent);
347+ out.print("try ");
348+ if (body != null) {
349+ body.print(out, indent);
350+ } else {
351+ out.print("<empty>");
352+ }
353+ out.print(" finally ");
354+ if (finalbody != null) {
355+ finalbody.print(out, indent);
356+ } else {
357+ out.print("<empty>");
358+ }
359+ }
360+}