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

Unified · Split

java/pkg/sun/tools/tree/Vset.java+518−0
@@ -0,0 +1,518 @@
1+/*
2+ * Copyright (c) 1996, 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+
26+package sun.tools.tree;
27+
28+import sun.tools.java.*;
29+
30+/**
31+ * WARNING: The contents of this source file are not part of any
32+ * supported API. Code that depends on them does so at its own risk:
33+ * they are subject to change or removal without notice.
34+ */
35+public final
36+class Vset implements Constants {
37+ long vset; // DA bits for first 64 variables
38+ long uset; // DU bits for first 64 variables
39+
40+ // The extension array is interleaved, consisting of alternating
41+ // blocks of 64 DA bits followed by 64 DU bits followed by 64 DA
42+ // bits, and so on.
43+
44+ long x[]; // extension array for more bits
45+
46+ // An infinite vector of zeroes or an infinite vector of ones is
47+ // represented by a special value of the extension array.
48+ //
49+ // IMPORTANT: The condition 'this.x == fullX' is used as a marker for
50+ // unreachable code, i.e., for a dead-end. We maintain the invariant
51+ // that (this.x != fullX || (this.vset == -1 && this.uset == -1)).
52+ // A dead-end has the peculiar property that all variables are both
53+ // definitely assigned and definitely unassigned. We always force this
54+ // condition to hold, even when the normal bitvector operations performed
55+ // during DA/DU analysis would produce a different result. This supresses
56+ // reporting of DA/DU errors in unreachable code.
57+
58+ static final long emptyX[] = new long[0]; // all zeroes
59+ static final long fullX[] = new long[0]; // all ones
60+
61+ // For more thorough testing of long vset support, it is helpful to
62+ // temporarily redefine this value to a smaller number, such as 1 or 2.
63+
64+ static final int VBITS = 64; // number of bits in vset (uset)
65+
66+ /**
67+ * This is the Vset which reports all vars assigned and unassigned.
68+ * This impossibility is degenerately true exactly when
69+ * control flow cannot reach this point.
70+ */
71+
72+ // We distinguish a canonical dead-end value generated initially for
73+ // statements that do not complete normally, making the next one unreachable.
74+ // Once an unreachable statement is reported, a non-canonical dead-end value
75+ // is used for subsequent statements in order to suppress redundant error
76+ // messages.
77+
78+ static final Vset DEAD_END = new Vset(-1, -1, fullX);
79+
80+ /**
81+ * Create an empty Vset.
82+ */
83+ public Vset() {
84+ this.x = emptyX;
85+ }
86+
87+ private Vset(long vset, long uset, long x[]) {
88+ this.vset = vset;
89+ this.uset = uset;
90+ this.x = x;
91+ }
92+
93+ /**
94+ * Create an copy of the given Vset.
95+ * (However, DEAD_END simply returns itself.)
96+ */
97+ public Vset copy() {
98+ if (this == DEAD_END) {
99+ return this;
100+ }
101+ Vset vs = new Vset(vset, uset, x);
102+ if (x.length > 0) {
103+ vs.growX(x.length); // recopy the extension vector
104+ }
105+ return vs;
106+ }
107+
108+ private void growX(int length) {
109+ long newX[] = new long[length];
110+ long oldX[] = x;
111+ for (int i = 0; i < oldX.length; i++) {
112+ newX[i] = oldX[i];
113+ }
114+ x = newX;
115+ }
116+
117+ /**
118+ * Ask if this is a vset for a dead end.
119+ * Answer true only for the canonical dead-end, DEAD_END.
120+ * A canonical dead-end is produced only as a result of
121+ * a statement that cannot complete normally, as specified
122+ * by the JLS. Due to the special-case rules for if-then
123+ * and if-then-else, this may fail to detect actual unreachable
124+ * code that could easily be identified.
125+ */
126+
127+ public boolean isDeadEnd() {
128+ return (this == DEAD_END);
129+ }
130+
131+ /**
132+ * Ask if this is a vset for a dead end.
133+ * Answer true for any dead-end.
134+ * Since 'clearDeadEnd' has no effect on this predicate,
135+ * if-then and if-then-else are handled in the more 'obvious'
136+ * and precise way. This predicate is to be preferred for
137+ * dead code elimination purposes.
138+ * (Presently used in workaround for bug 4173473 in MethodExpression.java)
139+ */
140+ public boolean isReallyDeadEnd() {
141+ return (x == fullX);
142+ }
143+
144+ /**
145+ * Replace canonical DEAD_END with a distinct but
146+ * equivalent Vset. The bits are unaltered, but
147+ * the result does not answer true to 'isDeadEnd'.
148+ * <p>
149+ * Used mostly for error recovery, but see
150+ * 'IfStatement.check', where it is used to
151+ * implement the special-case treatment of
152+ * statement reachability for such statements.
153+ */
154+ public Vset clearDeadEnd() {
155+ if (this == DEAD_END) {
156+ return new Vset(-1, -1, fullX);
157+ }
158+ return this;
159+ }
160+
161+ /**
162+ * Ask if a var is definitely assigned.
163+ */
164+ public boolean testVar(int varNumber) {
165+ long bit = (1L << varNumber);
166+ if (varNumber >= VBITS) {
167+ int i = (varNumber / VBITS - 1) * 2;
168+ if (i >= x.length) {
169+ return (x == fullX);
170+ }
171+ return (x[i] & bit) != 0;
172+ } else {
173+ return (vset & bit) != 0;
174+ }
175+ }
176+
177+ /**
178+ * Ask if a var is definitely un-assigned.
179+ * (This is not just the negation of testVar:
180+ * It's possible for neither to be true.)
181+ */
182+ public boolean testVarUnassigned(int varNumber) {
183+ long bit = (1L << varNumber);
184+ if (varNumber >= VBITS) {
185+ // index "uset" extension
186+ int i = ((varNumber / VBITS - 1) * 2) + 1;
187+ if (i >= x.length) {
188+ return (x == fullX);
189+ }
190+ return (x[i] & bit) != 0;
191+ } else {
192+ return (uset & bit) != 0;
193+ }
194+ }
195+
196+ /**
197+ * Note that a var is definitely assigned.
198+ * (Side-effecting.)
199+ */
200+ public Vset addVar(int varNumber) {
201+ if (x == fullX) {
202+ return this;
203+ }
204+
205+ // gen DA, kill DU
206+
207+ long bit = (1L << varNumber);
208+ if (varNumber >= VBITS) {
209+ int i = (varNumber / VBITS - 1) * 2;
210+ if (i >= x.length) {
211+ growX(i+1);
212+ }
213+ x[i] |= bit;
214+ if (i+1 < x.length) {
215+ x[i+1] &=~ bit;
216+ }
217+ } else {
218+ vset |= bit;
219+ uset &=~ bit;
220+ }
221+ return this;
222+ }
223+
224+ /**
225+ * Note that a var is definitely un-assigned.
226+ * (Side-effecting.)
227+ */
228+ public Vset addVarUnassigned(int varNumber) {
229+ if (x == fullX) {
230+ return this;
231+ }
232+
233+ // gen DU, kill DA
234+
235+ long bit = (1L << varNumber);
236+ if (varNumber >= VBITS) {
237+ // index "uset" extension
238+ int i = ((varNumber / VBITS - 1) * 2) + 1;
239+ if (i >= x.length) {
240+ growX(i+1);
241+ }
242+ x[i] |= bit;
243+ x[i-1] &=~ bit;
244+ } else {
245+ uset |= bit;
246+ vset &=~ bit;
247+ }
248+ return this;
249+ }
250+
251+ /**
252+ * Retract any assertion about the var.
253+ * This operation is ineffective on a dead-end.
254+ * (Side-effecting.)
255+ */
256+ public Vset clearVar(int varNumber) {
257+ if (x == fullX) {
258+ return this;
259+ }
260+ long bit = (1L << varNumber);
261+ if (varNumber >= VBITS) {
262+ int i = (varNumber / VBITS - 1) * 2;
263+ if (i >= x.length) {
264+ return this;
265+ }
266+ x[i] &=~ bit;
267+ if (i+1 < x.length) {
268+ x[i+1] &=~ bit;
269+ }
270+ } else {
271+ vset &=~ bit;
272+ uset &=~ bit;
273+ }
274+ return this;
275+ }
276+
277+ /**
278+ * Join with another vset. This is set intersection.
279+ * (Side-effecting.)
280+ */
281+ public Vset join(Vset other) {
282+
283+ // Return a dead-end if both vsets are dead-ends.
284+ // Return the canonical DEAD_END only if both vsets
285+ // are the canonical DEAD_END. Otherwise, an incoming
286+ // dead-end vset has already produced an error message,
287+ // and is now assumed to be reachable.
288+ if (this == DEAD_END) {
289+ return other.copy();
290+ }
291+ if (other == DEAD_END) {
292+ return this;
293+ }
294+ if (x == fullX) {
295+ return other.copy();
296+ }
297+ if (other.x == fullX) {
298+ return this;
299+ }
300+
301+ // DA = DA intersection DA
302+ // DU = DU intersection DU
303+
304+ vset &= other.vset;
305+ uset &= other.uset;
306+
307+ if (other.x == emptyX) {
308+ x = emptyX;
309+ } else {
310+ // ASSERT(otherX.length > 0);
311+ long otherX[] = other.x;
312+ int selfLength = x.length;
313+ int limit = (otherX.length < selfLength) ? otherX.length : selfLength;
314+ for (int i = 0; i < limit; i++) {
315+ x[i] &= otherX[i];
316+ }
317+ // If self is longer than other, all remaining
318+ // bits are implicitly 0. In the result, then,
319+ // the remaining DA and DU bits are cleared.
320+ for (int i = limit; i < selfLength; i++) {
321+ x[i] = 0;
322+ }
323+ }
324+ return this;
325+ }
326+
327+ /**
328+ * Add in the definite assignment bits of another vset,
329+ * but join the definite unassignment bits. This unusual
330+ * operation is used only for 'finally' blocks. The
331+ * original vset 'this' is destroyed by this operation.
332+ * (Part of fix for 4068688.)
333+ */
334+
335+ public Vset addDAandJoinDU(Vset other) {
336+
337+ // Return a dead-end if either vset is a dead end.
338+ // If either vset is the canonical DEAD_END, the
339+ // result is also the canonical DEAD_END.
340+ if (this == DEAD_END) {
341+ return this;
342+ }
343+ if (other == DEAD_END) {
344+ return other;
345+ }
346+ if (x == fullX) {
347+ return this;
348+ }
349+ if (other.x == fullX) {
350+ return other.copy();
351+ }
352+
353+ // DA = DA union DA'
354+ // DU = (DU intersection DU') - DA'
355+
356+ vset = vset | other.vset;
357+ uset = (uset & other.uset) & ~other.vset;
358+
359+ int selfLength = x.length;
360+ long otherX[] = other.x;
361+ int otherLength = otherX.length;
362+
363+ if (otherX != emptyX) {
364+ // ASSERT(otherX.length > 0);
365+ if (otherLength > selfLength) {
366+ growX(otherLength);
367+ }
368+ int i = 0;
369+ while (i < otherLength) {
370+ x[i] |= otherX[i];
371+ i++;
372+ if (i == otherLength) break;
373+ x[i] = ((x[i] & otherX[i]) & ~otherX[i-1]);
374+ i++;
375+ }
376+ }
377+ // If self is longer than other, all remaining
378+ // bits are implicitly 0. In the result, then,
379+ // the remaining DA bits are left unchanged, and
380+ // the DU bits are all cleared. First, align
381+ // index to the next block of DU bits (odd index).
382+ for (int i = (otherLength | 1); i < selfLength; i += 2) {
383+ x[i] = 0;
384+ }
385+ return this;
386+ }
387+
388+
389+ /**
390+ * Construct a vset consisting of the DA bits of the first argument
391+ * and the DU bits of the second argument. This is a higly unusual
392+ * operation, as it implies a case where the flowgraph for DA analysis
393+ * differs from that for DU analysis. It is only needed for analysing
394+ * 'try' blocks. The result is a dead-end iff the first argument is
395+ * dead-end. (Part of fix for 4068688.)
396+ */
397+
398+ public static Vset firstDAandSecondDU(Vset sourceDA, Vset sourceDU) {
399+
400+ // Note that reachability status is received via 'sourceDA' only!
401+ // This is a consequence of the fact that reachability and DA
402+ // analysis are performed on an identical flow graph, whereas the
403+ // flowgraph for DU analysis differs in the case of a 'try' statement.
404+ if (sourceDA.x == fullX) {
405+ return sourceDA.copy();
406+ }
407+
408+ long sourceDAx[] = sourceDA.x;
409+ int lenDA = sourceDAx.length;
410+ long sourceDUx[] = sourceDU.x;
411+ int lenDU = sourceDUx.length;
412+ int limit = (lenDA > lenDU) ? lenDA : lenDU;
413+ long x[] = emptyX;
414+
415+ if (limit > 0) {
416+ x = new long[limit];
417+ for (int i = 0; i < lenDA; i += 2) {
418+ x[i] = sourceDAx[i];
419+ }
420+ for (int i = 1; i < lenDU; i += 2) {
421+ x[i] = sourceDUx[i];
422+ }
423+ }
424+
425+ return new Vset(sourceDA.vset, sourceDU.uset, x);
426+ }
427+
428+ /**
429+ * Remove variables from the vset that are no longer part of
430+ * a context. Zeroes are stored past varNumber.
431+ * (Side-effecting.)<p>
432+ * However, if this is a dead end, keep it so.
433+ * That is, leave an infinite tail of bits set.
434+ */
435+ public Vset removeAdditionalVars(int varNumber) {
436+ if (x == fullX) {
437+ return this;
438+ }
439+ long bit = (1L << varNumber);
440+ if (varNumber >= VBITS) {
441+ int i = (varNumber / VBITS - 1) * 2;
442+ if (i < x.length) {
443+ x[i] &= (bit - 1);
444+ if (++i < x.length) {
445+ x[i] &= (bit - 1); // do the "uset" extension also
446+ }
447+ while (++i < x.length) {
448+ x[i] = 0;
449+ }
450+ }
451+ } else {
452+ if (x.length > 0) {
453+ x = emptyX;
454+ }
455+ vset &= (bit - 1);
456+ uset &= (bit - 1);
457+ }
458+ return this;
459+ }
460+
461+ /**
462+ * Return one larger than the highest bit set.
463+ */
464+ public int varLimit() {
465+ long vset;
466+ int result;
467+ scan: {
468+ for (int i = (x.length / 2) * 2; i >= 0; i -= 2) {
469+ if (i == x.length) continue; // oops
470+ vset = x[i];
471+ if (i+1 < x.length) {
472+ vset |= x[i+1]; // check the "uset" also
473+ }
474+ if (vset != 0) {
475+ result = (i/2 + 1) * VBITS;
476+ break scan;
477+ }
478+ }
479+ vset = this.vset;
480+ vset |= this.uset; // check the "uset" also
481+ if (vset != 0) {
482+ result = 0;
483+ break scan;
484+ } else {
485+ return 0;
486+ }
487+ }
488+ while (vset != 0) {
489+ result += 1;
490+ vset >>>= 1;
491+ }
492+ return result;
493+ }
494+
495+ public String toString() {
496+ if (this == DEAD_END)
497+ return "{DEAD_END}";
498+ StringBuffer sb = new StringBuffer("{");
499+ int maxVar = VBITS * (1 + (x.length+1)/2);
500+ for (int i = 0; i < maxVar; i++) {
501+ if (!testVarUnassigned(i)) {
502+ if (sb.length() > 1) {
503+ sb.append(' ');
504+ }
505+ sb.append(i);
506+ if (!testVar(i)) {
507+ sb.append('?'); // not definitely unassigned
508+ }
509+ }
510+ }
511+ if (x == fullX) {
512+ sb.append("...DEAD_END");
513+ }
514+ sb.append('}');
515+ return sb.toString();
516+ }
517+
518+}