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 }