1 /*
  2  * Copyright (c) 2026, 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 import jdk.internal.vm.annotation.Contended;
 24 import jdk.test.lib.valueclass.AsValueClass;
 25 
 26 /*
 27  * @test
 28  * @bug     8384107
 29  * @summary Test contended field layout and oop maps with flattened value types
 30  *
 31  * @library /test/lib
 32  * @modules java.base/jdk.internal.vm.annotation
 33  * @run main/othervm -XX:-RestrictContended -XX:ContendedPaddingWidth=128 -Xmx128m OopMapsCustomValue
 34  */
 35 public class OopMapsCustomValue {
 36     public static final int COUNT = 10000;
 37 
 38     // Small value type (32 bits) — guaranteed to be flattened
 39     @AsValueClass
 40     static class Small {
 41         int x;
 42         Small(int x) { this.x = x; }
 43     }
 44 
 45     // Value type with reference + primitive — flattened with compressed oops,
 46     // not flattened with full size oops, creating distinct layout patterns
 47     @AsValueClass
 48     static class Opt {
 49         Object o;
 50         boolean b;
 51         Opt(Object o, boolean b) { this.o = o; this.b = b; }
 52     }
 53 
 54     // Contended fields using exact value types for flattening
 55     public static class R0 {
 56         int i1;
 57         int i2;
 58         Small s01;
 59         Small s02;
 60         @Contended
 61         Small s03;
 62         @Contended
 63         Small s04;
 64         @Contended
 65         Opt opt01;
 66         @Contended
 67         Opt opt02;
 68     }
 69 
 70     public static class R1 extends R0 {
 71         int i3;
 72         int i4;
 73         Small s05;
 74         Small s06;
 75         @Contended
 76         Small s07;
 77         @Contended
 78         Small s08;
 79         @Contended
 80         Opt opt03;
 81         @Contended
 82         Opt opt04;
 83     }
 84 
 85     // Same-group contended with exact value types
 86     public static class G {
 87         @Contended("g1")
 88         Small s01;
 89         @Contended("g1")
 90         Opt opt01;
 91         @Contended("g2")
 92         Small s02;
 93         @Contended("g2")
 94         Opt opt02;
 95     }
 96 
 97     public static void main(String[] args) throws Exception {
 98         testContendedValueFields();
 99         testContendedSameGroup();
100     }
101 
102     static void testContendedValueFields() {
103         Object anchor = new Object();
104 
105         R1[] rs = new R1[COUNT];
106         for (int i = 0; i < COUNT; i++) {
107             R1 r = new R1();
108             r.s01 = new Small(1);
109             r.s02 = new Small(2);
110             r.s03 = new Small(3);
111             r.s04 = new Small(4);
112             r.opt01 = new Opt(anchor, true);
113             r.opt02 = new Opt(anchor, false);
114             r.i1 = 1;
115             r.i2 = 2;
116             r.s05 = new Small(5);
117             r.s06 = new Small(6);
118             r.s07 = new Small(7);
119             r.s08 = new Small(8);
120             r.opt03 = new Opt(anchor, true);
121             r.opt04 = new Opt(anchor, false);
122             r.i3 = 3;
123             r.i4 = 4;
124             rs[i] = r;
125         }
126 
127         System.gc();
128 
129         for (int i = 0; i < COUNT; i++) {
130             R1 r = rs[i];
131             if (r.s01.x != 1) throw new Error("s01");
132             if (r.s02.x != 2) throw new Error("s02");
133             if (r.s03.x != 3) throw new Error("s03");
134             if (r.s04.x != 4) throw new Error("s04");
135             if (r.opt01.o != anchor || r.opt01.b != true) throw new Error("opt01");
136             if (r.opt02.o != anchor || r.opt02.b != false) throw new Error("opt02");
137             if (r.i1 != 1) throw new Error("i1");
138             if (r.i2 != 2) throw new Error("i2");
139             if (r.s05.x != 5) throw new Error("s05");
140             if (r.s06.x != 6) throw new Error("s06");
141             if (r.s07.x != 7) throw new Error("s07");
142             if (r.s08.x != 8) throw new Error("s08");
143             if (r.opt03.o != anchor || r.opt03.b != true) throw new Error("opt03");
144             if (r.opt04.o != anchor || r.opt04.b != false) throw new Error("opt04");
145             if (r.i3 != 3) throw new Error("i3");
146             if (r.i4 != 4) throw new Error("i4");
147         }
148     }
149 
150     static void testContendedSameGroup() {
151         Object anchor = new Object();
152 
153         G[] gs = new G[COUNT];
154         for (int i = 0; i < COUNT; i++) {
155             G g = new G();
156             g.s01 = new Small(1);
157             g.opt01 = new Opt(anchor, true);
158             g.s02 = new Small(2);
159             g.opt02 = new Opt(anchor, false);
160             gs[i] = g;
161         }
162 
163         System.gc();
164 
165         for (int i = 0; i < COUNT; i++) {
166             G g = gs[i];
167             if (g.s01.x != 1) throw new Error("g1 s01");
168             if (g.opt01.o != anchor || g.opt01.b != true) throw new Error("g1 opt01");
169             if (g.s02.x != 2) throw new Error("g2 s02");
170             if (g.opt02.o != anchor || g.opt02.b != false) throw new Error("g2 opt02");
171         }
172     }
173 }