1 /* 2 * Copyright (c) 2024, 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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 import java.io.PrintStream; 25 import java.lang.runtime.CodeReflection; 26 import java.util.Spliterator; 27 import java.util.Spliterator.OfInt; 28 29 import static java.lang.System.out; 30 import static java.util.Spliterator.OfInt.*; 31 32 /* 33 * @test 34 * @summary Smoke test for code reflection with field access. 35 * @build FieldAccessTest 36 * @build CodeReflectionTester 37 * @run main CodeReflectionTester FieldAccessTest 38 */ 39 40 public class FieldAccessTest { 41 static int s_f; 42 int f; 43 44 @CodeReflection 45 @IR(""" 46 func @"test1" (%0 : FieldAccessTest)void -> { 47 %1 : int = constant @"1"; 48 field.store %1 @"FieldAccessTest::s_f()int"; 49 %2 : int = constant @"1"; 50 field.store %0 %2 @"FieldAccessTest::f()int"; 51 return; 52 }; 53 """) 54 void test1() { 55 s_f = 1; 56 f = 1; 57 } 58 59 @CodeReflection 60 @IR(""" 61 func @"test1_1" (%0 : FieldAccessTest)void -> { 62 %1 : int = field.load %0 @"FieldAccessTest::f()int"; 63 %2 : int = constant @"1"; 64 %3 : int = add %1 %2; 65 field.store %0 %3 @"FieldAccessTest::f()int"; 66 %4 : int = field.load @"FieldAccessTest::s_f()int"; 67 %5 : int = constant @"1"; 68 %6 : int = add %4 %5; 69 field.store %6 @"FieldAccessTest::s_f()int"; 70 return; 71 }; 72 """) 73 void test1_1() { 74 f += 1; 75 s_f += 1; 76 } 77 78 @CodeReflection 79 @IR(""" 80 func @"test2" (%0 : FieldAccessTest)void -> { 81 %1 : int = constant @"1"; 82 field.store %0 %1 @"FieldAccessTest::f()int"; 83 field.store %1 @"FieldAccessTest::s_f()int"; 84 return; 85 }; 86 """) 87 void test2() { 88 s_f = f = 1; 89 } 90 91 @CodeReflection 92 @IR(""" 93 func @"test2_1" (%0 : FieldAccessTest)void -> { 94 %1 : int = constant @"1"; 95 field.store %0 %1 @"FieldAccessTest::f()int"; 96 return; 97 }; 98 """) 99 void test2_1() { 100 this.f = 1; 101 } 102 103 @CodeReflection 104 @IR(""" 105 func @"test2_2" (%0 : FieldAccessTest)int -> { 106 %1 : int = field.load %0 @"FieldAccessTest::f()int"; 107 return %1; 108 }; 109 """) 110 int test2_2() { 111 return this.f; 112 } 113 114 @CodeReflection 115 @IR(""" 116 func @"test3" (%0 : FieldAccessTest)int -> { 117 %1 : int = field.load @"FieldAccessTest::s_f()int"; 118 %2 : int = field.load %0 @"FieldAccessTest::f()int"; 119 %3 : int = add %1 %2; 120 return %3; 121 }; 122 """) 123 int test3() { 124 return s_f + f; 125 } 126 127 static class A { 128 B b; 129 } 130 131 static class B { 132 C c; 133 } 134 135 static class C { 136 int f; 137 } 138 139 @CodeReflection 140 @IR(""" 141 func @"test4" (%0 : FieldAccessTest, %1 : FieldAccessTest$A)void -> { 142 %2 : Var<FieldAccessTest$A> = var %1 @"a"; 143 %3 : FieldAccessTest$A = var.load %2; 144 %4 : FieldAccessTest$B = field.load %3 @"FieldAccessTest$A::b()FieldAccessTest$B"; 145 %5 : FieldAccessTest$C = field.load %4 @"FieldAccessTest$B::c()FieldAccessTest$C"; 146 %6 : int = constant @"1"; 147 field.store %5 %6 @"FieldAccessTest$C::f()int"; 148 return; 149 }; 150 """) 151 void test4(A a) { 152 a.b.c.f = 1; 153 } 154 155 static class X { 156 int f; 157 static int s_f; 158 } 159 160 @CodeReflection 161 @IR(""" 162 func @"test5" (%0 : FieldAccessTest)int -> { 163 %1 : int = field.load @"FieldAccessTest$X::s_f()int"; 164 return %1; 165 }; 166 """) 167 int test5() { 168 return X.s_f; 169 } 170 171 @CodeReflection 172 @IR(""" 173 func @"test6" (%0 : FieldAccessTest)void -> { 174 %1 : int = constant @"1"; 175 field.store %1 @"FieldAccessTest$X::s_f()int"; 176 return; 177 }; 178 """) 179 void test6() { 180 X.s_f = 1; 181 } 182 183 184 @CodeReflection 185 @IR(""" 186 func @"test7" (%0 : FieldAccessTest)void -> { 187 %1 : int = field.load %0 @"FieldAccessTest::f()int"; 188 %2 : int = constant @"1"; 189 %3 : int = add %1 %2; 190 field.store %0 %3 @"FieldAccessTest::f()int"; 191 %4 : int = field.load @"FieldAccessTest::s_f()int"; 192 %5 : int = constant @"1"; 193 %6 : int = add %4 %5; 194 field.store %6 @"FieldAccessTest::s_f()int"; 195 return; 196 }; 197 """) 198 void test7() { 199 f += 1; 200 s_f += 1; 201 } 202 203 @CodeReflection 204 @IR(""" 205 func @"test8" (%0 : FieldAccessTest)void -> { 206 %1 : int = field.load %0 @"FieldAccessTest::f()int"; 207 %2 : int = constant @"1"; 208 %3 : int = add %1 %2; 209 field.store %0 %3 @"FieldAccessTest::f()int"; 210 %4 : int = field.load @"FieldAccessTest::s_f()int"; 211 %5 : int = constant @"1"; 212 %6 : int = add %4 %5; 213 field.store %6 @"FieldAccessTest::s_f()int"; 214 return; 215 }; 216 """) 217 void test8() { 218 this.f += 1; 219 this.s_f += 1; 220 } 221 222 @CodeReflection 223 @IR(""" 224 func @"test9" (%0 : FieldAccessTest)void -> { 225 %1 : int = field.load @"FieldAccessTest$X::s_f()int"; 226 %2 : int = constant @"1"; 227 %3 : int = add %1 %2; 228 field.store %3 @"FieldAccessTest$X::s_f()int"; 229 return; 230 }; 231 """) 232 void test9() { 233 X.s_f += 1; 234 } 235 236 @CodeReflection 237 @IR(""" 238 func @"test10" (%0 : FieldAccessTest)void -> { 239 %1 : int = field.load %0 @"FieldAccessTest::f()int"; 240 %2 : int = constant @"1"; 241 %3 : int = add %1 %2; 242 field.store %0 %3 @"FieldAccessTest::f()int"; 243 field.store %3 @"FieldAccessTest::s_f()int"; 244 return; 245 }; 246 """) 247 void test10() { 248 s_f = f += 1; 249 } 250 251 @CodeReflection 252 @IR(""" 253 func @"test11" (%0 : FieldAccessTest, %1 : FieldAccessTest$A)void -> { 254 %2 : Var<FieldAccessTest$A> = var %1 @"a"; 255 %3 : FieldAccessTest$A = var.load %2; 256 %4 : FieldAccessTest$B = field.load %3 @"FieldAccessTest$A::b()FieldAccessTest$B"; 257 %5 : FieldAccessTest$C = field.load %4 @"FieldAccessTest$B::c()FieldAccessTest$C"; 258 %6 : int = field.load %5 @"FieldAccessTest$C::f()int"; 259 %7 : int = constant @"1"; 260 %8 : int = add %6 %7; 261 field.store %5 %8 @"FieldAccessTest$C::f()int"; 262 return; 263 }; 264 """) 265 void test11(A a) { 266 a.b.c.f += 1; 267 } 268 269 @CodeReflection 270 @IR(""" 271 func @"test12" (%0 : FieldAccessTest)void -> { 272 %1 : int = field.load %0 @"FieldAccessTest::f()int"; 273 %2 : int = constant @"1"; 274 %3 : int = add %1 %2; 275 field.store %0 %3 @"FieldAccessTest::f()int"; 276 %4 : Var<int> = var %1 @"x"; 277 %5 : int = field.load %0 @"FieldAccessTest::f()int"; 278 %6 : int = constant @"1"; 279 %7 : int = sub %5 %6; 280 field.store %0 %7 @"FieldAccessTest::f()int"; 281 %8 : Var<int> = var %5 @"y"; 282 return; 283 }; 284 """) 285 void test12() { 286 int x = f++; 287 int y = f--; 288 } 289 290 @CodeReflection 291 @IR(""" 292 func @"test13" (%0 : FieldAccessTest)void -> { 293 %1 : int = field.load %0 @"FieldAccessTest::f()int"; 294 %2 : int = constant @"1"; 295 %3 : int = add %1 %2; 296 field.store %0 %3 @"FieldAccessTest::f()int"; 297 %4 : Var<int> = var %1 @"x"; 298 %5 : int = field.load %0 @"FieldAccessTest::f()int"; 299 %6 : int = constant @"1"; 300 %7 : int = sub %5 %6; 301 field.store %0 %7 @"FieldAccessTest::f()int"; 302 %8 : Var<int> = var %5 @"y"; 303 return; 304 }; 305 """) 306 void test13() { 307 int x = this.f++; 308 int y = this.f--; 309 } 310 311 @CodeReflection 312 @IR(""" 313 func @"test14" (%0 : FieldAccessTest)void -> { 314 %1 : int = field.load @"FieldAccessTest::s_f()int"; 315 %2 : int = constant @"1"; 316 %3 : int = add %1 %2; 317 field.store %3 @"FieldAccessTest::s_f()int"; 318 %4 : Var<int> = var %1 @"x"; 319 %5 : int = field.load @"FieldAccessTest::s_f()int"; 320 %6 : int = constant @"1"; 321 %7 : int = sub %5 %6; 322 field.store %7 @"FieldAccessTest::s_f()int"; 323 %8 : Var<int> = var %5 @"y"; 324 return; 325 }; 326 """) 327 void test14() { 328 int x = s_f++; 329 int y = s_f--; 330 } 331 332 @CodeReflection 333 @IR(""" 334 func @"test15" (%0 : FieldAccessTest, %1 : FieldAccessTest$X)void -> { 335 %2 : Var<FieldAccessTest$X> = var %1 @"h"; 336 %3 : FieldAccessTest$X = var.load %2; 337 %4 : int = field.load %3 @"FieldAccessTest$X::f()int"; 338 %5 : int = constant @"1"; 339 %6 : int = add %4 %5; 340 field.store %3 %6 @"FieldAccessTest$X::f()int"; 341 %7 : Var<int> = var %4 @"x"; 342 %8 : FieldAccessTest$X = var.load %2; 343 %9 : int = field.load %8 @"FieldAccessTest$X::f()int"; 344 %10 : int = constant @"1"; 345 %11 : int = sub %9 %10; 346 field.store %8 %11 @"FieldAccessTest$X::f()int"; 347 %12 : Var<int> = var %9 @"y"; 348 return; 349 }; 350 """) 351 void test15(X h) { 352 int x = h.f++; 353 int y = h.f--; 354 } 355 356 357 358 359 @CodeReflection 360 @IR(""" 361 func @"test16" (%0 : FieldAccessTest)void -> { 362 %1 : int = field.load %0 @"FieldAccessTest::f()int"; 363 %2 : int = constant @"1"; 364 %3 : int = add %1 %2; 365 field.store %0 %3 @"FieldAccessTest::f()int"; 366 %4 : Var<int> = var %3 @"x"; 367 %5 : int = field.load %0 @"FieldAccessTest::f()int"; 368 %6 : int = constant @"1"; 369 %7 : int = sub %5 %6; 370 field.store %0 %7 @"FieldAccessTest::f()int"; 371 %8 : Var<int> = var %7 @"y"; 372 return; 373 }; 374 """) 375 void test16() { 376 int x = ++f; 377 int y = --f; 378 } 379 380 @CodeReflection 381 @IR(""" 382 func @"test17" (%0 : FieldAccessTest)void -> { 383 %1 : int = field.load %0 @"FieldAccessTest::f()int"; 384 %2 : int = constant @"1"; 385 %3 : int = add %1 %2; 386 field.store %0 %3 @"FieldAccessTest::f()int"; 387 %4 : Var<int> = var %3 @"x"; 388 %5 : int = field.load %0 @"FieldAccessTest::f()int"; 389 %6 : int = constant @"1"; 390 %7 : int = sub %5 %6; 391 field.store %0 %7 @"FieldAccessTest::f()int"; 392 %8 : Var<int> = var %7 @"y"; 393 return; 394 }; 395 """) 396 void test17() { 397 int x = ++this.f; 398 int y = --this.f; 399 } 400 401 @CodeReflection 402 @IR(""" 403 func @"test18" (%0 : FieldAccessTest)void -> { 404 %1 : int = field.load @"FieldAccessTest::s_f()int"; 405 %2 : int = constant @"1"; 406 %3 : int = add %1 %2; 407 field.store %3 @"FieldAccessTest::s_f()int"; 408 %4 : Var<int> = var %3 @"x"; 409 %5 : int = field.load @"FieldAccessTest::s_f()int"; 410 %6 : int = constant @"1"; 411 %7 : int = sub %5 %6; 412 field.store %7 @"FieldAccessTest::s_f()int"; 413 %8 : Var<int> = var %7 @"y"; 414 return; 415 }; 416 """) 417 void test18() { 418 int x = ++s_f; 419 int y = --s_f; 420 } 421 422 @CodeReflection 423 @IR(""" 424 func @"test19" (%0 : FieldAccessTest, %1 : FieldAccessTest$X)void -> { 425 %2 : Var<FieldAccessTest$X> = var %1 @"h"; 426 %3 : FieldAccessTest$X = var.load %2; 427 %4 : int = field.load %3 @"FieldAccessTest$X::f()int"; 428 %5 : int = constant @"1"; 429 %6 : int = add %4 %5; 430 field.store %3 %6 @"FieldAccessTest$X::f()int"; 431 %7 : Var<int> = var %6 @"x"; 432 %8 : FieldAccessTest$X = var.load %2; 433 %9 : int = field.load %8 @"FieldAccessTest$X::f()int"; 434 %10 : int = constant @"1"; 435 %11 : int = sub %9 %10; 436 field.store %8 %11 @"FieldAccessTest$X::f()int"; 437 %12 : Var<int> = var %11 @"y"; 438 return; 439 }; 440 """) 441 void test19(X h) { 442 int x = ++h.f; 443 int y = --h.f; 444 } 445 446 static class Y extends X { 447 int yf; 448 static int s_yf; 449 450 @CodeReflection 451 @IR(""" 452 func @"test" (%0 : FieldAccessTest$Y)void -> { 453 %1 : int = field.load %0 @"FieldAccessTest$Y::f()int"; 454 %2 : Var<int> = var %1 @"x"; 455 %3 : int = field.load @"FieldAccessTest$Y::s_f()int"; 456 var.store %2 %3; 457 return; 458 }; 459 """) 460 void test() { 461 int x = f; 462 x = s_f; 463 } 464 465 @CodeReflection 466 @IR(""" 467 func @"test2" (%0 : FieldAccessTest$Y)void -> { 468 %1 : int = constant @"1"; 469 field.store %0 %1 @"FieldAccessTest$Y::f()int"; 470 %2 : int = constant @"1"; 471 field.store %2 @"FieldAccessTest$Y::s_f()int"; 472 return; 473 }; 474 """) 475 void test2() { 476 f = 1; 477 s_f = 1; 478 } 479 480 @CodeReflection 481 @IR(""" 482 func @"test3" (%0 : FieldAccessTest$Y)void -> { 483 %1 : int = field.load %0 @"FieldAccessTest$Y::f()int"; 484 %2 : int = constant @"1"; 485 %3 : int = add %1 %2; 486 field.store %0 %3 @"FieldAccessTest$Y::f()int"; 487 %4 : int = field.load @"FieldAccessTest$Y::s_f()int"; 488 %5 : int = constant @"1"; 489 %6 : int = add %4 %5; 490 field.store %6 @"FieldAccessTest$Y::s_f()int"; 491 return; 492 }; 493 """) 494 void test3() { 495 f++; 496 s_f++; 497 } 498 } 499 500 @CodeReflection 501 @IR(""" 502 func @"test20" (%0 : FieldAccessTest, %1 : FieldAccessTest$Y)void -> { 503 %2 : Var<FieldAccessTest$Y> = var %1 @"y"; 504 %3 : FieldAccessTest$Y = var.load %2; 505 %4 : int = field.load %3 @"FieldAccessTest$Y::f()int"; 506 %5 : Var<int> = var %4 @"x"; 507 %6 : FieldAccessTest$Y = var.load %2; 508 %7 : int = field.load %6 @"FieldAccessTest$Y::yf()int"; 509 var.store %5 %7; 510 %8 : FieldAccessTest$Y = var.load %2; 511 %9 : int = field.load @"FieldAccessTest$Y::s_yf()int"; 512 var.store %5 %9; 513 %10 : int = field.load @"FieldAccessTest$Y::s_yf()int"; 514 var.store %5 %10; 515 %11 : FieldAccessTest$Y = var.load %2; 516 %12 : int = field.load @"FieldAccessTest$Y::s_f()int"; 517 var.store %5 %12; 518 %13 : int = field.load @"FieldAccessTest$Y::s_f()int"; 519 var.store %5 %13; 520 return; 521 }; 522 """) 523 void test20(Y y) { 524 int x = y.f; 525 x = y.yf; 526 x = y.s_yf; 527 x = Y.s_yf; 528 x = y.s_f; 529 x = Y.s_f; 530 } 531 532 @CodeReflection 533 @IR(""" 534 func @"test21" (%0 : FieldAccessTest, %1 : FieldAccessTest$Y)void -> { 535 %2 : Var<FieldAccessTest$Y> = var %1 @"y"; 536 %3 : FieldAccessTest$Y = var.load %2; 537 %4 : int = constant @"1"; 538 field.store %3 %4 @"FieldAccessTest$Y::f()int"; 539 %5 : FieldAccessTest$Y = var.load %2; 540 %6 : int = constant @"1"; 541 field.store %5 %6 @"FieldAccessTest$Y::yf()int"; 542 %7 : FieldAccessTest$Y = var.load %2; 543 %8 : int = constant @"1"; 544 field.store %8 @"FieldAccessTest$Y::s_yf()int"; 545 %9 : int = constant @"1"; 546 field.store %9 @"FieldAccessTest$Y::s_yf()int"; 547 %10 : FieldAccessTest$Y = var.load %2; 548 %11 : int = constant @"1"; 549 field.store %11 @"FieldAccessTest$Y::s_f()int"; 550 %12 : int = constant @"1"; 551 field.store %12 @"FieldAccessTest$Y::s_f()int"; 552 return; 553 }; 554 """) 555 void test21(Y y) { 556 y.f = 1; 557 y.yf = 1; 558 y.s_yf = 1; 559 Y.s_yf = 1; 560 y.s_f = 1; 561 Y.s_f = 1; 562 } 563 564 @CodeReflection 565 @IR(""" 566 func @"test22" (%0 : FieldAccessTest, %1 : FieldAccessTest$Y)void -> { 567 %2 : Var<FieldAccessTest$Y> = var %1 @"y"; 568 %3 : FieldAccessTest$Y = var.load %2; 569 %4 : int = field.load %3 @"FieldAccessTest$Y::f()int"; 570 %5 : int = constant @"1"; 571 %6 : int = add %4 %5; 572 field.store %3 %6 @"FieldAccessTest$Y::f()int"; 573 %7 : FieldAccessTest$Y = var.load %2; 574 %8 : int = field.load %7 @"FieldAccessTest$Y::yf()int"; 575 %9 : int = constant @"1"; 576 %10 : int = add %8 %9; 577 field.store %7 %10 @"FieldAccessTest$Y::yf()int"; 578 %11 : FieldAccessTest$Y = var.load %2; 579 %12 : int = field.load @"FieldAccessTest$Y::s_yf()int"; 580 %13 : int = constant @"1"; 581 %14 : int = add %12 %13; 582 field.store %14 @"FieldAccessTest$Y::s_yf()int"; 583 %15 : int = field.load @"FieldAccessTest$Y::s_yf()int"; 584 %16 : int = constant @"1"; 585 %17 : int = add %15 %16; 586 field.store %17 @"FieldAccessTest$Y::s_yf()int"; 587 %18 : FieldAccessTest$Y = var.load %2; 588 %19 : int = field.load @"FieldAccessTest$Y::s_f()int"; 589 %20 : int = constant @"1"; 590 %21 : int = add %19 %20; 591 field.store %21 @"FieldAccessTest$Y::s_f()int"; 592 %22 : int = field.load @"FieldAccessTest$Y::s_f()int"; 593 %23 : int = constant @"1"; 594 %24 : int = add %22 %23; 595 field.store %24 @"FieldAccessTest$Y::s_f()int"; 596 return; 597 }; 598 """) 599 void test22(Y y) { 600 y.f++; 601 y.yf++; 602 y.s_yf++; 603 Y.s_yf++; 604 y.s_f++; 605 Y.s_f++; 606 } 607 608 // @@@ Should propagate as constant value? 609 @CodeReflection 610 @IR(""" 611 func @"test23" (%0 : FieldAccessTest)void -> { 612 %1 : int = field.load @"java.util.Spliterator$OfInt::CONCURRENT()int"; 613 %2 : Var<int> = var %1 @"x"; 614 %3 : int = field.load @"java.util.Spliterator$OfInt::CONCURRENT()int"; 615 var.store %2 %3; 616 %4 : int = field.load @"java.util.Spliterator$OfInt::CONCURRENT()int"; 617 var.store %2 %4; 618 return; 619 }; 620 """) 621 void test23() { 622 int x = Spliterator.OfInt.CONCURRENT; 623 x = OfInt.CONCURRENT; 624 x = CONCURRENT; 625 } 626 627 @CodeReflection 628 @IR(""" 629 func @"test24" (%0 : FieldAccessTest)void -> { 630 %1 : java.io.PrintStream = field.load @"java.lang.System::out()java.io.PrintStream"; 631 %2 : Var<java.io.PrintStream> = var %1 @"ps"; 632 return; 633 }; 634 """) 635 void test24() { 636 PrintStream ps = out; 637 } 638 639 static class Box<T> { 640 public T v; 641 642 public Box(T v) { 643 this.v = v; 644 } 645 } 646 647 @CodeReflection 648 @IR(""" 649 func @"test25" ()void -> { 650 %0 : java.lang.String = constant @"abc"; 651 %1 : FieldAccessTest$Box<java.lang.String> = new %0 @"func<FieldAccessTest$Box, java.lang.Object>"; 652 %2 : Var<FieldAccessTest$Box<java.lang.String>> = var %1 @"b"; 653 %3 : FieldAccessTest$Box<java.lang.String> = var.load %2; 654 %4 : java.lang.String = field.load %3 @"FieldAccessTest$Box::v()java.lang.Object"; 655 %5 : Var<java.lang.String> = var %4 @"s"; 656 return; 657 }; 658 """) 659 static void test25() { 660 Box<String> b = new Box<>("abc"); 661 String s = b.v; 662 } 663 664 //@@@ unqualified access to field of generic type needs to be tested 665 // waiting for a new way of modeling types, so that type variables are captured in the IR 666 }