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/IfStatement.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/tools/tree/IfStatement.java+203−0
@@ -0,0 +1,203 @@
1/*
2 * Copyright (c) 1994, 2003, 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
26package sun.tools.tree;
27
28import sun.tools.java.*;
29import sun.tools.asm.Assembler;
30import sun.tools.asm.Label;
31import java.io.PrintStream;
32import java.util.Hashtable;
33
34/**
35 * WARNING: The contents of this source file are not part of any
36 * supported API. Code that depends on them does so at its own risk:
37 * they are subject to change or removal without notice.
38 */
39public
40class IfStatement extends Statement {
41 Expression cond;
42 Statement ifTrue;
43 Statement ifFalse;
44
45 /**
46 * Constructor
47 */
48 public IfStatement(long where, Expression cond, Statement ifTrue, Statement ifFalse) {
49 super(IF, where);
50 this.cond = cond;
51 this.ifTrue = ifTrue;
52 this.ifFalse = ifFalse;
53 }
54
55 /**
56 * Check statement
57 */
58 Vset check(Environment env, Context ctx, Vset vset, Hashtable exp) {
59 checkLabel(env, ctx);
60 CheckContext newctx = new CheckContext(ctx, this);
61 // Vset vsExtra = vset.copy(); // See comment below.
62 ConditionVars cvars =
63 cond.checkCondition(env, newctx, reach(env, vset), exp);
64 cond = convert(env, newctx, Type.tBoolean, cond);
65 // The following code, now deleted, was apparently an erroneous attempt
66 // at providing better error diagnostics. The comment read: 'If either
67 // the true clause or the false clause is unreachable, do a reasonable
68 // check on the child anyway.'
69 // Vset vsTrue = cvars.vsTrue.isDeadEnd() ? vsExtra : cvars.vsTrue;
70 // Vset vsFalse = cvars.vsFalse.isDeadEnd() ? vsExtra : cvars.vsFalse;
71 // Unfortunately, this violates the rules laid out in the JLS, and leads to
72 // blatantly incorrect results. For example, 'i' will not be recognized
73 // as definitely assigned following the statement 'if (true) i = 1;'.
74 // It is best to slavishly follow the JLS here. A cleverer approach could
75 // only correctly issue warnings, as JLS 16.2.6 is quite explicit, and it
76 // is OK for a dead branch of an if-statement to omit an assignment that
77 // would be required in the other branch. A complication: This code also
78 // had the effect of implementing the special-case rules for 'if-then' and
79 // 'if-then-else' in JLS 14.19, "Unreachable Statements". We now use
80 // 'Vset.clearDeadEnd' to remove the dead-end status of unreachable branches
81 // without affecting the definite-assignment status of the variables, thus
82 // maintaining a correct implementation of JLS 16.2.6. Fixes 4094353.
83 // Note that the code below will not consider the branches unreachable if
84 // the entire statement is unreachable. This is consistent with the error
85 // recovery policy that reports the only the first unreachable statement
86 // along an acyclic execution path.
87 Vset vsTrue = cvars.vsTrue.clearDeadEnd();
88 Vset vsFalse = cvars.vsFalse.clearDeadEnd();
89 vsTrue = ifTrue.check(env, newctx, vsTrue, exp);
90 if (ifFalse != null)
91 vsFalse = ifFalse.check(env, newctx, vsFalse, exp);
92 vset = vsTrue.join(vsFalse.join(newctx.vsBreak));
93 return ctx.removeAdditionalVars(vset);
94 }
95
96 /**
97 * Inline
98 */
99 public Statement inline(Environment env, Context ctx) {
100 ctx = new Context(ctx, this);
101 cond = cond.inlineValue(env, ctx);
102
103 // The compiler currently needs to perform inlining on both
104 // branches of the if statement -- even if `cond' is a constant
105 // true or false. Why? The compiler will later try to compile
106 // all classes that it has seen; this includes classes that
107 // appear in dead code. If we don't inline the dead branch here
108 // then the compiler will never perform inlining on any local
109 // classes appearing on the dead code. When the compiler tries
110 // to compile an un-inlined local class with uplevel references,
111 // it dies. (bug 4059492)
112 //
113 // A better solution to this would be to walk the dead branch and
114 // mark any local classes appearing therein as unneeded. Then the
115 // compilation phase could skip these classes.
116 if (ifTrue != null) {
117 ifTrue = ifTrue.inline(env, ctx);
118 }
119 if (ifFalse != null) {
120 ifFalse = ifFalse.inline(env, ctx);
121 }
122 if (cond.equals(true)) {
123 return eliminate(env, ifTrue);
124 }
125 if (cond.equals(false)) {
126 return eliminate(env, ifFalse);
127 }
128 if ((ifTrue == null) && (ifFalse == null)) {
129 return eliminate(env, new ExpressionStatement(where, cond).inline(env, ctx));
130 }
131 if (ifTrue == null) {
132 cond = new NotExpression(cond.where, cond).inlineValue(env, ctx);
133 return eliminate(env, new IfStatement(where, cond, ifFalse, null));
134 }
135 return this;
136 }
137
138 /**
139 * Create a copy of the statement for method inlining
140 */
141 public Statement copyInline(Context ctx, boolean valNeeded) {
142 IfStatement s = (IfStatement)clone();
143 s.cond = cond.copyInline(ctx);
144 if (ifTrue != null) {
145 s.ifTrue = ifTrue.copyInline(ctx, valNeeded);
146 }
147 if (ifFalse != null) {
148 s.ifFalse = ifFalse.copyInline(ctx, valNeeded);
149 }
150 return s;
151 }
152
153 /**
154 * The cost of inlining this statement
155 */
156 public int costInline(int thresh, Environment env, Context ctx) {
157 int cost = 1 + cond.costInline(thresh, env, ctx);
158 if (ifTrue != null) {
159 cost += ifTrue.costInline(thresh, env, ctx);
160 }
161 if (ifFalse != null) {
162 cost += ifFalse.costInline(thresh, env, ctx);
163 }
164 return cost;
165 }
166
167 /**
168 * Code
169 */
170 public void code(Environment env, Context ctx, Assembler asm) {
171 CodeContext newctx = new CodeContext(ctx, this);
172
173 Label l1 = new Label();
174 cond.codeBranch(env, newctx, asm, l1, false);
175 ifTrue.code(env, newctx, asm);
176 if (ifFalse != null) {
177 Label l2 = new Label();
178 asm.add(true, where, opc_goto, l2);
179 asm.add(l1);
180 ifFalse.code(env, newctx, asm);
181 asm.add(l2);
182 } else {
183 asm.add(l1);
184 }
185
186 asm.add(newctx.breakLabel);
187 }
188
189 /**
190 * Print
191 */
192 public void print(PrintStream out, int indent) {
193 super.print(out, indent);
194 out.print("if ");
195 cond.print(out);
196 out.print(" ");
197 ifTrue.print(out, indent);
198 if (ifFalse != null) {
199 out.print(" else ");
200 ifFalse.print(out, indent);
201 }
202 }
203}