PageRenderTime 115ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/java-1.7.0-openjdk/openjdk/jdk/src/share/classes/sun/tools/tree/Vset.java

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