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