Lines 24-33
Link Here
|
24 |
* No caching of pre-allocated instances. |
24 |
* No caching of pre-allocated instances. |
25 |
*/ |
25 |
*/ |
26 |
public class UnconditionalFlowInfo extends FlowInfo { |
26 |
public class UnconditionalFlowInfo extends FlowInfo { |
27 |
// Coverage tests |
|
|
28 |
/** |
27 |
/** |
29 |
* Exception raised when unexpected behavior is detected during coverage |
28 |
* Exception raised when unexpected behavior is detected. |
30 |
* tests. |
|
|
31 |
*/ |
29 |
*/ |
32 |
public static class AssertionFailedException extends RuntimeException { |
30 |
public static class AssertionFailedException extends RuntimeException { |
33 |
private static final long serialVersionUID = 1827352841030089703L; |
31 |
private static final long serialVersionUID = 1827352841030089703L; |
Lines 976-982
Link Here
|
976 |
& (this.extra[4][vectorIndex] ^ this.extra[5][vectorIndex]) |
974 |
& (this.extra[4][vectorIndex] ^ this.extra[5][vectorIndex]) |
977 |
& (1L << (position % BitCacheSize))) != 0; |
975 |
& (1L << (position % BitCacheSize))) != 0; |
978 |
} |
976 |
} |
979 |
|
977 |
/** Asserts that the given boolean is <code>true</code>. If this |
|
|
978 |
* is not the case, some kind of unchecked exception is thrown. |
979 |
* The given message is included in that exception, to aid debugging. |
980 |
* |
981 |
* @param expression the outcome of the check |
982 |
* @param message the message to include in the exception |
983 |
* @return <code>true</code> if the check passes (does not return |
984 |
* if the check fails) |
985 |
*/ |
986 |
private static boolean isTrue(boolean expression, String message) { |
987 |
if (!expression) |
988 |
throw new AssertionFailedException("assertion failed: " + message); //$NON-NLS-1$ |
989 |
return expression; |
990 |
} |
980 |
public void markAsComparedEqualToNonNull(LocalVariableBinding local) { |
991 |
public void markAsComparedEqualToNonNull(LocalVariableBinding local) { |
981 |
// protected from non-object locals in calling methods |
992 |
// protected from non-object locals in calling methods |
982 |
if (this != DEAD_END) { |
993 |
if (this != DEAD_END) { |
Lines 1330-1335
Link Here
|
1330 |
} |
1341 |
} |
1331 |
} |
1342 |
} |
1332 |
|
1343 |
|
|
|
1344 |
public void resetNullInfo(LocalVariableBinding local) { |
1345 |
if (this != DEAD_END) { |
1346 |
this.tagBits |= NULL_FLAG_MASK; |
1347 |
int position; |
1348 |
long mask; |
1349 |
if ((position = local.id + this.maxFieldCount) < BitCacheSize) { |
1350 |
// use bits |
1351 |
this.nullBit1 &= (mask = ~(1L << position)); |
1352 |
this.nullBit2 &= mask; |
1353 |
this.nullBit3 &= mask; |
1354 |
this.nullBit4 &= mask; |
1355 |
} else { |
1356 |
// use extra vector |
1357 |
int vectorIndex ; |
1358 |
this.extra[2][vectorIndex = (position / BitCacheSize) - 1] |
1359 |
&= (mask = ~(1L << (position % BitCacheSize))); |
1360 |
this.extra[3][vectorIndex] &= mask; |
1361 |
this.extra[4][vectorIndex] &= mask; |
1362 |
this.extra[5][vectorIndex] &= mask; |
1363 |
} |
1364 |
} |
1365 |
} |
1366 |
|
1367 |
/** |
1368 |
* Mark a local as potentially having been assigned to an unknown value. |
1369 |
* @param local the local to mark |
1370 |
*/ |
1371 |
public void markAsPotentiallyUnknown(LocalVariableBinding local) { |
1372 |
// protected from non-object locals in calling methods |
1373 |
if (this != DEAD_END) { |
1374 |
this.tagBits |= NULL_FLAG_MASK; |
1375 |
int position; |
1376 |
long mask; |
1377 |
if ((position = local.id + this.maxFieldCount) < BitCacheSize) { |
1378 |
// use bits |
1379 |
mask = 1L << position; |
1380 |
isTrue((this.nullBit1 & mask) == 0, "Adding 'unknown' mark in unexpected state"); //$NON-NLS-1$ |
1381 |
this.nullBit4 |= mask; |
1382 |
if (COVERAGE_TEST_FLAG) { |
1383 |
if(CoverageTestId == 46) { |
1384 |
this.nullBit4 = ~0; |
1385 |
} |
1386 |
} |
1387 |
} else { |
1388 |
// use extra vector |
1389 |
int vectorIndex = (position / BitCacheSize) - 1; |
1390 |
mask = 1L << (position % BitCacheSize); |
1391 |
isTrue((this.extra[2][vectorIndex] & mask) == 0, "Adding 'unknown' mark in unexpected state"); //$NON-NLS-1$ |
1392 |
this.extra[5][vectorIndex] |= mask; |
1393 |
if (COVERAGE_TEST_FLAG) { |
1394 |
if(CoverageTestId == 47) { |
1395 |
this.extra[5][vectorIndex] = ~0; |
1396 |
} |
1397 |
} |
1398 |
} |
1399 |
} |
1400 |
} |
1401 |
|
1333 |
public void markAsPotentiallyNull(LocalVariableBinding local) { |
1402 |
public void markAsPotentiallyNull(LocalVariableBinding local) { |
1334 |
if (this != DEAD_END) { |
1403 |
if (this != DEAD_END) { |
1335 |
this.tagBits |= NULL_FLAG_MASK; |
1404 |
this.tagBits |= NULL_FLAG_MASK; |
Lines 1337-1346
Link Here
|
1337 |
long mask; |
1406 |
long mask; |
1338 |
if ((position = local.id + this.maxFieldCount) < BitCacheSize) { |
1407 |
if ((position = local.id + this.maxFieldCount) < BitCacheSize) { |
1339 |
// use bits |
1408 |
// use bits |
1340 |
this.nullBit1 &= ~(mask = 1L << position); |
1409 |
mask = 1L << position; |
|
|
1410 |
isTrue((this.nullBit1 & mask) == 0, "Adding 'potentially null' mark in unexpected state"); //$NON-NLS-1$ |
1341 |
this.nullBit2 |= mask; |
1411 |
this.nullBit2 |= mask; |
1342 |
this.nullBit3 &= ~mask; |
|
|
1343 |
this.nullBit4 &= ~mask; |
1344 |
if (COVERAGE_TEST_FLAG) { |
1412 |
if (COVERAGE_TEST_FLAG) { |
1345 |
if(CoverageTestId == 40) { |
1413 |
if(CoverageTestId == 40) { |
1346 |
this.nullBit4 = ~0; |
1414 |
this.nullBit4 = ~0; |
Lines 1348-1359
Link Here
|
1348 |
} |
1416 |
} |
1349 |
} else { |
1417 |
} else { |
1350 |
// use extra vector |
1418 |
// use extra vector |
1351 |
int vectorIndex ; |
1419 |
int vectorIndex = (position / BitCacheSize) - 1; |
1352 |
this.extra[2][vectorIndex = (position / BitCacheSize) - 1] |
1420 |
mask = 1L << (position % BitCacheSize); |
1353 |
&= ~(mask = 1L << (position % BitCacheSize)); |
|
|
1354 |
this.extra[3][vectorIndex] |= mask; |
1421 |
this.extra[3][vectorIndex] |= mask; |
1355 |
this.extra[4][vectorIndex] &= (mask = ~mask); |
1422 |
isTrue((this.extra[2][vectorIndex] & mask) == 0, "Adding 'potentially null' mark in unexpected state"); //$NON-NLS-1$ |
1356 |
this.extra[5][vectorIndex] &= mask; |
|
|
1357 |
if (COVERAGE_TEST_FLAG) { |
1423 |
if (COVERAGE_TEST_FLAG) { |
1358 |
if(CoverageTestId == 41) { |
1424 |
if(CoverageTestId == 41) { |
1359 |
this.extra[5][vectorIndex] = ~0; |
1425 |
this.extra[5][vectorIndex] = ~0; |
Lines 1363-1368
Link Here
|
1363 |
} |
1429 |
} |
1364 |
} |
1430 |
} |
1365 |
|
1431 |
|
|
|
1432 |
public void markAsPotentiallyNonNull(LocalVariableBinding local) { |
1433 |
if (this != DEAD_END) { |
1434 |
this.tagBits |= NULL_FLAG_MASK; |
1435 |
int position; |
1436 |
long mask; |
1437 |
if ((position = local.id + this.maxFieldCount) < BitCacheSize) { |
1438 |
// use bits |
1439 |
mask = 1L << position; |
1440 |
isTrue((this.nullBit1 & mask) == 0, "Adding 'potentially non-null' mark in unexpected state"); //$NON-NLS-1$ |
1441 |
this.nullBit3 |= mask; |
1442 |
if (COVERAGE_TEST_FLAG) { |
1443 |
if(CoverageTestId == 42) { |
1444 |
this.nullBit4 = ~0; |
1445 |
} |
1446 |
} |
1447 |
} else { |
1448 |
// use extra vector |
1449 |
int vectorIndex = (position / BitCacheSize) - 1; |
1450 |
mask = 1L << (position % BitCacheSize); |
1451 |
isTrue((this.extra[2][vectorIndex] & mask) == 0, "Adding 'potentially non-null' mark in unexpected state"); //$NON-NLS-1$ |
1452 |
this.extra[4][vectorIndex] |= mask; |
1453 |
if (COVERAGE_TEST_FLAG) { |
1454 |
if(CoverageTestId == 43) { |
1455 |
this.extra[5][vectorIndex] = ~0; |
1456 |
} |
1457 |
} |
1458 |
} |
1459 |
} |
1460 |
} |
1461 |
|
1366 |
public UnconditionalFlowInfo mergedWith(UnconditionalFlowInfo otherInits) { |
1462 |
public UnconditionalFlowInfo mergedWith(UnconditionalFlowInfo otherInits) { |
1367 |
if ((otherInits.tagBits & UNREACHABLE) != 0 && this != DEAD_END) { |
1463 |
if ((otherInits.tagBits & UNREACHABLE) != 0 && this != DEAD_END) { |
1368 |
if (COVERAGE_TEST_FLAG) { |
1464 |
if (COVERAGE_TEST_FLAG) { |