1 /* 2 * Copyright (c) 2017, 2019, 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 25 import java.lang.management.MemoryPoolMXBean; 26 27 import sun.hotspot.WhiteBox; 28 import jdk.test.lib.Asserts; 29 30 /** 31 * @test ValueTypeDensity 32 * @summary Heap density test for ValueTypes 33 * @library /test/lib 34 * @compile -XDemitQtypes -XDenableValueTypes -XDallowWithFieldOperator ValueTypeDensity.java 35 * @run driver ClassFileInstaller sun.hotspot.WhiteBox 36 * @run main/othervm -Xint -XX:ValueArrayElemMaxFlatSize=-1 37 * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions 38 * -XX:+WhiteBoxAPI ValueTypeDensity 39 * @run main/othervm -Xcomp -XX:ValueArrayElemMaxFlatSize=-1 40 * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions 41 * -XX:+WhiteBoxAPI ValueTypeDensity 42 * @run main/othervm -Xbatch -XX:ForceNonTearable=* 43 * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions 44 * -XX:+WhiteBoxAPI ValueTypeDensity 45 */ 46 47 public class ValueTypeDensity { 48 49 private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); 50 51 public ValueTypeDensity() { 52 if (WHITE_BOX.getIntxVMFlag("ValueArrayElemMaxFlatSize") != -1) { 53 throw new IllegalStateException("ValueArrayElemMaxFlatSize should be -1"); 54 } 55 } 56 57 interface LocalDate { 58 public int getYear(); 59 public short getMonth(); 60 public short getDay(); 61 } 62 63 interface LocalTime { 64 public byte getHour(); 65 public byte getMinute(); 66 public byte getSecond(); 67 public int getNano(); 68 } 69 70 interface LocalDateTime extends LocalDate, LocalTime {} 71 72 static final inline class LocalDateValue implements LocalDate { 73 final int year; 74 final short month; 75 final short day; 76 77 LocalDateValue() { 78 year = 0; 79 month = 0; 80 day = 0; 81 } 82 83 public int getYear() { return year; } 84 public short getMonth() { return month; } 85 public short getDay() { return day; } 86 87 public static LocalDateValue create(int year, short month, short day) { 88 LocalDateValue localDate = LocalDateValue.default; 89 localDate = __WithField(localDate.year, year); 90 localDate = __WithField(localDate.month, month); 91 localDate = __WithField(localDate.day, day); 92 return localDate; 93 } 94 } 95 96 static final inline class LocalTimeValue implements LocalTime { 97 final byte hour; 98 final byte minute; 99 final byte second; 100 final int nano; 101 102 LocalTimeValue() { 103 hour = 0; 104 minute = 0; 105 second = 0; 106 nano = 0; 107 } 108 109 public byte getHour() { return hour; } 110 public byte getMinute() { return minute; } 111 public byte getSecond() { return second; } 112 public int getNano() { return nano; } 113 114 public static LocalTimeValue create(byte hour, byte minute, byte second, int nano) { 115 LocalTimeValue localTime = LocalTimeValue.default; 116 localTime = __WithField(localTime.hour, hour); 117 localTime = __WithField(localTime.minute, minute); 118 localTime = __WithField(localTime.second, second); 119 localTime = __WithField(localTime.nano, nano); 120 return localTime; 121 } 122 } 123 124 static final inline class LocalDateTimeValue implements LocalDateTime { 125 final LocalDateValue date; 126 final LocalTimeValue time; 127 128 LocalDateTimeValue() { 129 // Well this is a little weird... 130 date = LocalDateValue.create(0, (short)0, (short)0); 131 time = LocalTimeValue.create((byte)0, (byte)0, (byte)0, 0); 132 } 133 134 public int getYear() { return date.year; } 135 public short getMonth() { return date.month; } 136 public short getDay() { return date.day; } 137 138 public byte getHour() { return time.hour; } 139 public byte getMinute() { return time.minute; } 140 public byte getSecond() { return time.second; } 141 public int getNano() { return time.nano; } 142 143 public static LocalDateTimeValue create(LocalDateValue date, LocalTimeValue time) { 144 LocalDateTimeValue localDateTime = LocalDateTimeValue.default; 145 localDateTime = __WithField(localDateTime.date, date); 146 localDateTime = __WithField(localDateTime.time, time); 147 return localDateTime; 148 } 149 } 150 151 static final class LocalDateClass implements LocalDate { 152 final int year; 153 final short month; 154 final short day; 155 156 LocalDateClass(int year, short month, short day) { 157 this.year = year; 158 this.month = month; 159 this.day = day; 160 } 161 162 public int getYear() { return year; } 163 public short getMonth() { return month; } 164 public short getDay() { return day; } 165 } 166 167 static final class LocalTimeClass implements LocalTime { 168 final byte hour; 169 final byte minute; 170 final byte second; 171 final int nano; 172 173 LocalTimeClass(byte hour, byte minute, byte second, int nano) { 174 this.hour = hour; 175 this.minute = minute; 176 this.second = second; 177 this.nano = nano; 178 } 179 180 public byte getHour() { return hour; } 181 public byte getMinute() { return minute; } 182 public byte getSecond() { return second; } 183 public int getNano() { return nano; } 184 } 185 186 static final class LocalDateTimeClass implements LocalDateTime { 187 final LocalDateClass date; 188 final LocalTimeClass time; 189 190 LocalDateTimeClass(LocalDateClass date, LocalTimeClass time) { 191 this.date = date; 192 this.time = time; 193 } 194 195 public LocalDateClass getDate() { return date; } 196 public LocalTimeClass getTime() { return time; } 197 198 public int getYear() { return date.year; } 199 public short getMonth() { return date.month; } 200 public short getDay() { return date.day; } 201 202 public byte getHour() { return time.hour; } 203 public byte getMinute() { return time.minute; } 204 public byte getSecond() { return time.second; } 205 public int getNano() { return time.nano; } 206 } 207 208 public void ensureArraySizeWin() { 209 int arrayLength = 1000; 210 System.out.println("ensureArraySizeWin for length " + arrayLength); 211 LocalDateTimeClass[] objectArray = new LocalDateTimeClass[arrayLength]; 212 for (int i = 0; i < arrayLength; i++) { 213 objectArray[i] = new LocalDateTimeClass(new LocalDateClass(0, (short)0, (short)0), 214 new LocalTimeClass((byte)0, (byte)0, (byte)0, 0)); 215 } 216 217 long objectArraySize = WHITE_BOX.getObjectSize(objectArray); 218 System.out.println("Empty object array size: " + objectArraySize); 219 objectArraySize += (arrayLength * 220 (WHITE_BOX.getObjectSize(objectArray[0]) + 221 WHITE_BOX.getObjectSize(objectArray[0].getDate()) + 222 WHITE_BOX.getObjectSize(objectArray[0].getTime()))); 223 224 LocalDateTimeValue[] valueArray = new LocalDateTimeValue[arrayLength]; 225 // CMH: add "isFlatValueArray" to WhiteBox API, to ensure we are correctly account size 226 227 long valueArraySize = WHITE_BOX.getObjectSize(valueArray); 228 System.out.println("Object array and elements: " + objectArraySize + " versus Value Array: " + valueArraySize); 229 Asserts.assertLessThan(valueArraySize, objectArraySize, "Value array accounts for more heap than object array + elements !"); 230 } 231 232 public void test() { 233 ensureArraySizeWin(); 234 } 235 236 public static void main(String[] args) { 237 new ValueTypeDensity().test(); 238 } 239 240 } 241