|
23 | 23 |
|
24 | 24 | /**
|
25 | 25 | * @test
|
26 |
| - * @bug 8259609 |
| 26 | + * @bug 8259609 8276116 |
27 | 27 | * @summary C2: optimize long range checks in long counted loops
|
28 | 28 | * @requires vm.compiler2.enabled
|
29 | 29 | * @requires vm.compMode != "Xcomp"
|
|
32 | 32 | * @build sun.hotspot.WhiteBox
|
33 | 33 | * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox
|
34 | 34 | *
|
35 |
| - * @run main/othervm -ea -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-BackgroundCompilation TestLongRangeCheck |
| 35 | + * @run main/othervm -ea -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestLongRangeCheck |
36 | 36 | *
|
37 | 37 | */
|
38 | 38 |
|
@@ -193,6 +193,115 @@ public static void main(String[] args) throws Exception {
|
193 | 193 | m.invoke(null, 0, 100, Long.MAX_VALUE, Long.MAX_VALUE - 50, 0, 50);
|
194 | 194 | assertIsCompiled(m);
|
195 | 195 | }
|
| 196 | + |
| 197 | + test("testStridePosScalePosInIntLoop", 0, 100, 100, 0); |
| 198 | + |
| 199 | + test("testStrideNegScaleNegInIntLoop", 0, 100, 100, 100); |
| 200 | + |
| 201 | + test("testStrideNegScalePosInIntLoop", 0, 100, 100, 0); |
| 202 | + |
| 203 | + test("testStridePosScaleNegInIntLoop", 0, 100, 100, 99); |
| 204 | + |
| 205 | + test("testStridePosScalePosNotOneInIntLoop", 0, 100, 1090, 0); |
| 206 | + |
| 207 | + test("testStrideNegScaleNegNotOneInIntLoop", 0, 100, 1090, 1100); |
| 208 | + |
| 209 | + test("testStrideNegScalePosNotOneInIntLoop", 0, 100, 1090, 0); |
| 210 | + |
| 211 | + test("testStridePosScaleNegNotOneInIntLoop", 0, 100, 1090, 1089); |
| 212 | + |
| 213 | + v = ((long)Integer.MAX_VALUE / 10000) * 9999; |
| 214 | + |
| 215 | + test("testStridePosNotOneScalePosInIntLoop", -v, v, v * 4, 2 * v); |
| 216 | + |
| 217 | + test("testStrideNegNotOneScaleNegInIntLoop", -v, v, v * 4, 2 * v); |
| 218 | + |
| 219 | + test("testStrideNegNotOneScalePosInIntLoop", -v, v, v * 4, 2 * v); |
| 220 | + |
| 221 | + test("testStridePosNotOneScaleNegInIntLoop", -v, v, v * 4, 2 * v - 1); |
| 222 | + |
| 223 | + // offset causes overflow |
| 224 | + { |
| 225 | + Method m = newClassLoader().loadClass("TestLongRangeCheck").getDeclaredMethod("testStridePosScalePosInIntLoop", long.class, long.class, long.class, long.class); |
| 226 | + m.invoke(null, 0, 100, 100, 0); |
| 227 | + compile(m); |
| 228 | + |
| 229 | + m.invoke(null, 0, 100, 100, 0); |
| 230 | + assertIsCompiled(m); |
| 231 | + try { |
| 232 | + m.invoke(null, 0, 100, 100, Long.MAX_VALUE - 50); |
| 233 | + throw new RuntimeException("should have thrown"); |
| 234 | + } catch(InvocationTargetException e) { |
| 235 | + if (!(e.getCause() instanceof IndexOutOfBoundsException)) { |
| 236 | + throw new RuntimeException("unexpected exception"); |
| 237 | + } |
| 238 | + } |
| 239 | + assertIsNotCompiled(m); |
| 240 | + } |
| 241 | + // no spurious deopt if the range check doesn't fail because not executed |
| 242 | + { |
| 243 | + Method m = newClassLoader().loadClass("TestLongRangeCheck").getDeclaredMethod("testStridePosScalePosConditional", long.class, long.class, long.class, long.class, long.class, long.class); |
| 244 | + m.invoke(null, 0, 100, 100, 0, 0, 100); |
| 245 | + compile(m); |
| 246 | + |
| 247 | + m.invoke(null, 0, 100, 100, -50, 50, 100); |
| 248 | + assertIsCompiled(m); |
| 249 | + } |
| 250 | + { |
| 251 | + Method m = newClassLoader().loadClass("TestLongRangeCheck").getDeclaredMethod("testStridePosScalePosConditional", long.class, long.class, long.class, long.class, long.class, long.class); |
| 252 | + m.invoke(null, 0, 100, 100, 0, 0, 100); |
| 253 | + compile(m); |
| 254 | + |
| 255 | + m.invoke(null, 0, 100, Long.MAX_VALUE, Long.MAX_VALUE - 50, 0, 50); |
| 256 | + assertIsCompiled(m); |
| 257 | + } |
| 258 | + |
| 259 | + test("testStridePosScalePosNotOneInIntLoop2", 0, 100, 1090, 0); |
| 260 | + |
| 261 | + test("testStrideNegScaleNegNotOneInIntLoop2", 0, 100, 1090, 1100); |
| 262 | + |
| 263 | + test("testStrideNegScalePosNotOneInIntLoop2", 0, 100, 1090, 0); |
| 264 | + |
| 265 | + test("testStridePosScaleNegNotOneInIntLoop2", 0, 100, 1090, 1089); |
| 266 | + |
| 267 | + { |
| 268 | + Method m = newClassLoader().loadClass("TestLongRangeCheck").getDeclaredMethod("testStridePosScalePosInIntLoopOverflow", long.class, long.class, long.class, long.class); |
| 269 | + long stride = 1 << 14; |
| 270 | + long scale = 1 << 15; |
| 271 | + long offset = stride * scale * 4; |
| 272 | + long length = offset + stride * scale * 3 + 1; |
| 273 | + long stop = stride * 5; |
| 274 | + |
| 275 | + m.invoke(null, 0, stop, length, offset); |
| 276 | + compile(m); |
| 277 | + |
| 278 | + m.invoke(null, 0, stop, length, offset); |
| 279 | + // deoptimizes even though no range check fails |
| 280 | + } |
| 281 | + { |
| 282 | + Method m = newClassLoader().loadClass("TestLongRangeCheck").getDeclaredMethod("testStridePosScalePosInIntLoopOverflow", long.class, long.class, long.class, long.class); |
| 283 | + long stride = 1 << 14; |
| 284 | + long scale = 1 << 15; |
| 285 | + long offset = stride * scale * 4; |
| 286 | + long length = offset + stride * scale * 3 + 1; |
| 287 | + long stop = stride * 5; |
| 288 | + |
| 289 | + m.invoke(null, 0, stop, length, offset); |
| 290 | + compile(m); |
| 291 | + |
| 292 | + offset = 0; |
| 293 | + stop = stride * 5; |
| 294 | + |
| 295 | + try { |
| 296 | + m.invoke(null, 0, stop, length, offset); |
| 297 | + throw new RuntimeException("should have thrown"); |
| 298 | + } catch(InvocationTargetException e) { |
| 299 | + if (!(e.getCause() instanceof IndexOutOfBoundsException)) { |
| 300 | + throw new RuntimeException("unexpected exception"); |
| 301 | + } |
| 302 | + } |
| 303 | + assertIsNotCompiled(m); |
| 304 | + } |
196 | 305 | }
|
197 | 306 |
|
198 | 307 | public static void testStridePosScalePos(long start, long stop, long length, long offset) {
|
@@ -301,4 +410,177 @@ public static void testStridePosScalePosConditional(long start, long stop, long
|
301 | 410 | }
|
302 | 411 | }
|
303 | 412 | }
|
| 413 | + |
| 414 | + private static void checkInputs(long... inputs) { |
| 415 | + for (int i = 0; i < inputs.length; i++) { |
| 416 | + if ((long)((int)inputs[i]) != inputs[i]) { |
| 417 | + throw new RuntimeException("bad arguments"); |
| 418 | + } |
| 419 | + } |
| 420 | + } |
| 421 | + |
| 422 | + public static void testStridePosScalePosInIntLoop(long start, long stop, long length, long offset) { |
| 423 | + checkInputs(start, stop); |
| 424 | + final long scale = 1; |
| 425 | + final int stride = 1; |
| 426 | + for (int i = (int)start; i < (int)stop; i += stride) { |
| 427 | + Preconditions.checkIndex(scale * i + offset, length, null); |
| 428 | + } |
| 429 | + } |
| 430 | + |
| 431 | + public static void testStrideNegScaleNegInIntLoop(long start, long stop, long length, long offset) { |
| 432 | + checkInputs(start, stop); |
| 433 | + final long scale = -1; |
| 434 | + final int stride = 1; |
| 435 | + for (int i = (int)stop; i > (int)start; i -= stride) { |
| 436 | + Preconditions.checkIndex(scale * i + offset, length, null); |
| 437 | + } |
| 438 | + } |
| 439 | + |
| 440 | + public static void testStrideNegScalePosInIntLoop(long start, long stop, long length, long offset) { |
| 441 | + checkInputs(start, stop); |
| 442 | + final long scale = 1; |
| 443 | + final int stride = 1; |
| 444 | + for (int i = (int)(stop-1); i >= (int)start; i -= stride) { |
| 445 | + Preconditions.checkIndex(scale * i + offset, length, null); |
| 446 | + } |
| 447 | + } |
| 448 | + |
| 449 | + public static void testStridePosScaleNegInIntLoop(long start, long stop, long length, long offset) { |
| 450 | + checkInputs(start, stop); |
| 451 | + final long scale = -1; |
| 452 | + final int stride = 1; |
| 453 | + for (int i = (int)start; i < (int)stop; i += stride) { |
| 454 | + Preconditions.checkIndex(scale * i + offset, length, null); |
| 455 | + } |
| 456 | + } |
| 457 | + |
| 458 | + public static void testStridePosScalePosNotOneInIntLoop(long start, long stop, long length, long offset) { |
| 459 | + checkInputs(start, stop); |
| 460 | + final long scale = 11; |
| 461 | + final int stride = 1; |
| 462 | + for (int i = (int)start; i < (int)stop; i += stride) { |
| 463 | + Preconditions.checkIndex(scale * i + offset, length, null); |
| 464 | + } |
| 465 | + } |
| 466 | + |
| 467 | + public static void testStrideNegScaleNegNotOneInIntLoop(long start, long stop, long length, long offset) { |
| 468 | + checkInputs(start, stop); |
| 469 | + final long scale = -11; |
| 470 | + final int stride = 1; |
| 471 | + for (int i = (int)stop; i > (int)start; i -= stride) { |
| 472 | + Preconditions.checkIndex(scale * i + offset, length, null); |
| 473 | + } |
| 474 | + } |
| 475 | + |
| 476 | + public static void testStrideNegScalePosNotOneInIntLoop(long start, long stop, long length, long offset) { |
| 477 | + checkInputs(start, stop); |
| 478 | + final long scale = 11; |
| 479 | + final int stride = 1; |
| 480 | + for (int i = (int)(stop-1); i >= (int)start; i -= stride) { |
| 481 | + Preconditions.checkIndex(scale * i + offset, length, null); |
| 482 | + } |
| 483 | + } |
| 484 | + |
| 485 | + public static void testStridePosScaleNegNotOneInIntLoop(long start, long stop, long length, long offset) { |
| 486 | + checkInputs(start, stop); |
| 487 | + final long scale = -11; |
| 488 | + final int stride = 1; |
| 489 | + for (int i = (int)start; i < (int)stop; i += stride) { |
| 490 | + Preconditions.checkIndex(scale * i + offset, length, null); |
| 491 | + } |
| 492 | + } |
| 493 | + |
| 494 | + public static void testStridePosNotOneScalePosInIntLoop(long start, long stop, long length, long offset) { |
| 495 | + checkInputs(start, stop); |
| 496 | + final long scale = 2; |
| 497 | + final int stride = Integer.MAX_VALUE / 10000; |
| 498 | + for (int i = (int)start; i < (int)stop; i += stride) { |
| 499 | + Preconditions.checkIndex(scale * i + offset, length, null); |
| 500 | + } |
| 501 | + } |
| 502 | + |
| 503 | + public static void testStrideNegNotOneScaleNegInIntLoop(long start, long stop, long length, long offset) { |
| 504 | + checkInputs(start, stop); |
| 505 | + final long scale = -2; |
| 506 | + final int stride = Integer.MAX_VALUE / 10000; |
| 507 | + for (int i = (int)stop; i > (int)start; i -= stride) { |
| 508 | + Preconditions.checkIndex(scale * i + offset, length, null); |
| 509 | + } |
| 510 | + } |
| 511 | + |
| 512 | + public static void testStrideNegNotOneScalePosInIntLoop(long start, long stop, long length, long offset) { |
| 513 | + checkInputs(start, stop); |
| 514 | + final long scale = 2; |
| 515 | + final int stride = Integer.MAX_VALUE / 10000; |
| 516 | + for (int i = (int)(stop-1); i >= (int)start; i -= stride) { |
| 517 | + Preconditions.checkIndex(scale * i + offset, length, null); |
| 518 | + } |
| 519 | + } |
| 520 | + |
| 521 | + public static void testStridePosNotOneScaleNegInIntLoop(long start, long stop, long length, long offset) { |
| 522 | + checkInputs(start, stop); |
| 523 | + final long scale = -2; |
| 524 | + final int stride = Integer.MAX_VALUE / 10000; |
| 525 | + for (int i = (int)start; i < (int)stop; i += stride) { |
| 526 | + Preconditions.checkIndex(scale * i + offset, length, null); |
| 527 | + } |
| 528 | + } |
| 529 | + |
| 530 | + public static void testStridePosScalePosConditionalInIntLoop(long start, long stop, long length, long offset, long start2, long stop2) { |
| 531 | + checkInputs(start, stop, start2, stop2); |
| 532 | + Preconditions.checkIndex(0, length, null); |
| 533 | + final long scale = 1; |
| 534 | + final int stride = 1; |
| 535 | + for (int i = (int)start; i < (int)stop; i += stride) { |
| 536 | + if (i >= (int)start2 && i < (int)stop2) { |
| 537 | + Preconditions.checkIndex(scale * i + offset, length, null); |
| 538 | + } |
| 539 | + } |
| 540 | + } |
| 541 | + |
| 542 | + public static void testStridePosScalePosNotOneInIntLoop2(long start, long stop, long length, long offset) { |
| 543 | + checkInputs(start, stop); |
| 544 | + final int scale = 11; |
| 545 | + final int stride = 1; |
| 546 | + for (int i = (int)start; i < (int)stop; i += stride) { |
| 547 | + Preconditions.checkIndex(scale * i + offset, length, null); |
| 548 | + } |
| 549 | + } |
| 550 | + |
| 551 | + public static void testStrideNegScaleNegNotOneInIntLoop2(long start, long stop, long length, long offset) { |
| 552 | + checkInputs(start, stop); |
| 553 | + final int scale = -11; |
| 554 | + final int stride = 1; |
| 555 | + for (int i = (int)stop; i > (int)start; i -= stride) { |
| 556 | + Preconditions.checkIndex(scale * i + offset, length, null); |
| 557 | + } |
| 558 | + } |
| 559 | + |
| 560 | + public static void testStrideNegScalePosNotOneInIntLoop2(long start, long stop, long length, long offset) { |
| 561 | + checkInputs(start, stop); |
| 562 | + final int scale = 11; |
| 563 | + final int stride = 1; |
| 564 | + for (int i = (int)(stop-1); i >= (int)start; i -= stride) { |
| 565 | + Preconditions.checkIndex(scale * i + offset, length, null); |
| 566 | + } |
| 567 | + } |
| 568 | + |
| 569 | + public static void testStridePosScaleNegNotOneInIntLoop2(long start, long stop, long length, long offset) { |
| 570 | + checkInputs(start, stop); |
| 571 | + final int scale = -11; |
| 572 | + final int stride = 1; |
| 573 | + for (int i = (int)start; i < (int)stop; i += stride) { |
| 574 | + Preconditions.checkIndex(scale * i + offset, length, null); |
| 575 | + } |
| 576 | + } |
| 577 | + |
| 578 | + public static void testStridePosScalePosInIntLoopOverflow(long start, long stop, long length, long offset) { |
| 579 | + checkInputs(start, stop); |
| 580 | + final int scale = 1 << 15; |
| 581 | + final int stride = 1 << 14; |
| 582 | + for (int i = (int)start; i < (int)stop; i += stride) { |
| 583 | + Preconditions.checkIndex(scale * i + offset, length, null); |
| 584 | + } |
| 585 | + } |
304 | 586 | }
|
0 commit comments