1 /* 2 * Copyright (c) 2019, 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 package runtime.valhalla.valuetypes; 24 25 import jdk.test.lib.Asserts; 26 27 import java.lang.reflect.Field; 28 29 /* 30 * @test 31 * @summary Test support for empty value types (no instance fields) 32 * @library /test/lib 33 * @compile -XDallowEmptyValues EmptyValueTest.java 34 * @run main/othervm -XX:+EnableValhalla runtime.valhalla.valuetypes.EmptyValueTest 35 36 */ 37 38 public class EmptyValueTest { 39 40 static inline class EmptyValue { 41 public boolean isEmpty() { 42 return true; 43 } 44 } 45 46 static inline class EmptyField { 47 EmptyValue empty; 48 49 EmptyField() { 50 this.empty = new EmptyValue(); 51 } 52 } 53 54 static class WithInt { 55 int i; 56 } 57 58 static class WithEmptyField extends WithInt { 59 // With current layout strategy for reference classs, the empty 60 // value field would be placed between the int and the Object 61 // fields, along with some padding. 62 Object o; 63 EmptyValue empty; 64 } 65 66 public static void main(String[] args) { 67 // Create an empty value 68 EmptyValue empty = new EmptyValue(); 69 Asserts.assertTrue(empty.isEmpty()); 70 71 // Create a value with a empty value field 72 EmptyField emptyField = new EmptyField(); 73 Asserts.assertTrue(emptyField.empty.isEmpty()); 74 System.out.println(emptyField.empty.isEmpty()); 75 76 // Regular instance with an empty field inside 77 WithEmptyField w = new WithEmptyField(); 78 Asserts.assertTrue(w.empty.isEmpty()); 79 w.empty = new EmptyValue(); 80 Asserts.assertTrue(w.empty.isEmpty()); 81 82 // Create an array of empty values 83 EmptyValue[] emptyArray = new EmptyValue[100]; 84 for(EmptyValue element : emptyArray) { 85 Asserts.assertTrue(element.isEmpty()); 86 } 87 88 // Testing arrayCopy 89 EmptyValue[] array2 = new EmptyValue[100]; 90 // with two arrays 91 System.arraycopy(emptyArray, 10, array2, 20, 50); 92 for(EmptyValue element : array2) { 93 Asserts.assertTrue(element.isEmpty()); 94 } 95 // single array, no overlap 96 System.arraycopy(emptyArray, 10, emptyArray, 50, 20); 97 for(EmptyValue element : emptyArray) { 98 Asserts.assertTrue(element.isEmpty()); 99 } 100 // single array with overlap 101 System.arraycopy(emptyArray, 10, emptyArray, 20, 50); 102 for(EmptyValue element : emptyArray) { 103 Asserts.assertTrue(element.isEmpty()); 104 } 105 106 // Passing an empty value in argument 107 assert isEmpty(empty); 108 109 // Returning an empty value 110 assert getEmpty().isEmpty(); 111 112 // Checking fields with reflection 113 Class<?> c = empty.getClass(); 114 try { 115 Field[] fields = c.getDeclaredFields(); 116 Asserts.assertTrue(fields.length == 0); 117 } catch (Throwable t) { 118 t.printStackTrace(); 119 } 120 121 // Testing JIT compiler 122 // for(int i=0; i < 100000; i++) { 123 // test(); 124 // } 125 } 126 127 static boolean isEmpty(EmptyValue empty) { 128 return empty.isEmpty(); 129 } 130 131 static EmptyValue getEmpty() { 132 return new EmptyValue(); 133 } 134 135 static void test() { 136 for(int i=0; i < 10000; i++) { 137 Asserts.assertTrue(getEmpty().isEmpty()); 138 } 139 } 140 }