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