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 package runtime.valhalla.valuetypes; 25 26 import java.io.File; 27 import java.io.IOException; 28 import java.io.PrintWriter; 29 import java.lang.invoke.*; 30 import java.lang.ref.*; 31 import java.util.ArrayList; 32 import java.util.Arrays; 33 import java.util.List; 34 import java.util.concurrent.*; 35 36 import static jdk.test.lib.Asserts.*; 37 38 import jdk.experimental.bytecode.MacroCodeBuilder; 39 import jdk.experimental.bytecode.MacroCodeBuilder.CondKind; 40 import jdk.experimental.bytecode.TypeTag; 41 import jdk.test.lib.Platform; 42 import jdk.test.lib.Utils; 43 44 import jdk.experimental.value.MethodHandleBuilder; 45 46 import javax.tools.*; 47 48 /** 49 * @test ValueTypesTest 50 * @summary Test data movement with inline types 51 * @modules java.base/jdk.experimental.bytecode 52 * java.base/jdk.experimental.value 53 * @library /test/lib 54 * @compile -XDemitQtypes -XDenableValueTypes -XDallowWithFieldOperator TestValue1.java TestValue2.java TestValue3.java TestValue4.java ValueTypesTest.java 55 * @run main/othervm -Xint -Xmx128m -XX:-ShowMessageBoxOnError 56 * -XX:+ExplicitGCInvokesConcurrent 57 * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions 58 * -Djava.lang.invoke.MethodHandle.DUMP_CLASS_FILES=false 59 * runtime.valhalla.valuetypes.ValueTypesTest 60 * @run main/othervm -Xcomp -Xmx128m -XX:-ShowMessageBoxOnError 61 * -XX:+ExplicitGCInvokesConcurrent 62 * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions 63 * -Djava.lang.invoke.MethodHandle.DUMP_CLASS_FILES=false 64 * runtime.valhalla.valuetypes.ValueTypesTest 65 * @run main/othervm -Xbatch -Xmx128m -XX:-ShowMessageBoxOnError 66 * -XX:+ExplicitGCInvokesConcurrent 67 * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions 68 * -Djava.lang.invoke.MethodHandle.DUMP_CLASS_FILES=false 69 * -XX:ForceNonTearable=* 70 * runtime.valhalla.valuetypes.ValueTypesTest 71 */ 72 public class ValueTypesTest { 73 74 public static void main(String[] args) { 75 Class<?> inlineClass = runtime.valhalla.valuetypes.TestValue1.class; 76 Class<?> testClasses[] = { 77 runtime.valhalla.valuetypes.TestValue1.class, 78 runtime.valhalla.valuetypes.TestValue2.class, 79 runtime.valhalla.valuetypes.TestValue3.class, 80 runtime.valhalla.valuetypes.TestValue4.class 81 }; 82 Class<?> containerClasses[] = { 83 runtime.valhalla.valuetypes.ContainerValue1.class, 84 runtime.valhalla.valuetypes.ContainerValue2.class, 85 runtime.valhalla.valuetypes.ContainerValue3.class, 86 runtime.valhalla.valuetypes.ContainerValue4.class 87 }; 88 89 for (int i = 0; i < testClasses.length; i++) { 90 try { 91 testExecutionStackToLocalVariable(testClasses[i]); 92 testExecutionStackToFields(testClasses[i], containerClasses[i]); 93 // testExecutionStackToValueArray(testClasses[i], containerClasses[i]); 94 } catch (Throwable t) { 95 t.printStackTrace(); 96 throw new RuntimeException(t); 97 } 98 } 99 } 100 101 static MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); 102 103 static void testExecutionStackToLocalVariable(Class<?> inlineClass) throws Throwable { 104 String sig = "()Q" + inlineClass.getName() + ";"; 105 final String signature = sig.replace('.', '/'); 106 MethodHandle fromExecStackToLocalVar = MethodHandleBuilder.loadCode( 107 LOOKUP, 108 "execStackToLocalVar", 109 MethodType.methodType(boolean.class), 110 CODE -> { 111 CODE.invokestatic(System.class, "gc", "()V", false); 112 int n = -1; 113 while (n < 1024) { 114 n++; 115 CODE 116 .invokestatic(inlineClass, "getInstance", signature, false) 117 .astore(n); 118 n++; 119 CODE 120 .invokestatic(inlineClass, "getNonBufferedInstance", signature, false) 121 .astore(n); 122 } 123 CODE.invokestatic(System.class, "gc", "()V", false); 124 while (n > 0) { 125 CODE 126 .aload(n) 127 .invokevirtual(inlineClass, "verify", "()Z", false) 128 .iconst_1() 129 .ifcmp(TypeTag.I, CondKind.NE, "end"); 130 n--; 131 } 132 CODE 133 .iconst_1() 134 .return_(TypeTag.Z) 135 .label("end") 136 .iconst_0() 137 .return_(TypeTag.Z); 138 }); 139 boolean result = (boolean) fromExecStackToLocalVar.invokeExact(); 140 System.out.println(result); 141 assertTrue(result, "Invariant"); 142 } 143 144 static void testExecutionStackToFields(Class<?> inlineClass, Class<?> containerClass) throws Throwable { 145 final int ITERATIONS = Platform.isDebugBuild() ? 3 : 512; 146 String sig = "()Q" + inlineClass.getName() + ";"; 147 final String methodSignature = sig.replace('.', '/'); 148 final String fieldQSignature = "Q" + inlineClass.getName().replace('.', '/') + ";"; 149 final String fieldLSignature = "L" + inlineClass.getName().replace('.', '/') + ";"; 150 System.out.println(methodSignature); 151 MethodHandle fromExecStackToFields = MethodHandleBuilder.loadCode( 152 LOOKUP, 153 "execStackToFields", 154 MethodType.methodType(boolean.class), 155 CODE -> { 156 CODE 157 .invokestatic(System.class, "gc", "()V", false) 158 .new_(containerClass) 159 .dup() 160 .invoke(MacroCodeBuilder.InvocationKind.INVOKESPECIAL, containerClass, "<init>", "()V", false) 161 .astore_1() 162 .iconst_m1() 163 .istore_2() 164 .label("loop") 165 .iload_2() 166 .ldc(ITERATIONS) 167 .ifcmp(TypeTag.I, CondKind.EQ, "end") 168 .aload_1() 169 .invokestatic(inlineClass, "getInstance", methodSignature, false) 170 .putfield(containerClass, "nonStaticValueField", fieldQSignature) 171 .invokestatic(System.class, "gc", "()V", false) 172 .aload_1() 173 .getfield(containerClass, "nonStaticValueField", fieldQSignature) 174 .invokevirtual(inlineClass, "verify", "()Z", false) 175 .iconst_1() 176 .ifcmp(TypeTag.I, CondKind.NE, "failed") 177 .aload_1() 178 .invokestatic(inlineClass, "getNonBufferedInstance", methodSignature, false) 179 .putfield(containerClass, "nonStaticValueField", fieldQSignature) 180 .invokestatic(System.class, "gc", "()V", false) 181 .aload_1() 182 .getfield(containerClass, "nonStaticValueField", fieldQSignature) 183 .invokevirtual(inlineClass, "verify", "()Z", false) 184 .iconst_1() 185 .ifcmp(TypeTag.I, CondKind.NE, "failed") 186 .invokestatic(inlineClass, "getInstance", methodSignature, false) 187 .putstatic(containerClass, "staticValueField", fieldLSignature) 188 .invokestatic(System.class, "gc", "()V", false) 189 .getstatic(containerClass, "staticValueField", fieldLSignature) 190 .invokevirtual(inlineClass, "verify", "()Z", false) 191 .iconst_1() 192 .ifcmp(TypeTag.I, CondKind.NE, "failed") 193 .invokestatic(inlineClass, "getNonBufferedInstance", methodSignature, false) 194 .putstatic(containerClass, "staticValueField", fieldLSignature) 195 .invokestatic(System.class, "gc", "()V", false) 196 .getstatic(containerClass, "staticValueField", fieldLSignature) 197 .invokevirtual(inlineClass, "verify", "()Z", false) 198 .iconst_1() 199 .ifcmp(TypeTag.I, CondKind.NE, "failed") 200 .iinc(2, 1) 201 .goto_("loop") 202 .label("end") 203 .iconst_1() 204 .return_(TypeTag.Z) 205 .label("failed") 206 .iconst_0() 207 .return_(TypeTag.Z); 208 }); 209 boolean result = (boolean) fromExecStackToFields.invokeExact(); 210 System.out.println(result); 211 assertTrue(result, "Invariant"); 212 } 213 214 static void testExecutionStackToValueArray(Class<?> inlineClass, Class<?> containerClass) throws Throwable { 215 final int ITERATIONS = Platform.isDebugBuild() ? 3 : 100; 216 String sig = "()Q" + inlineClass.getName() + ";"; 217 final String signature = sig.replace('.', '/'); 218 final String arraySignature = "[L" + inlineClass.getName().replace('.', '/') + ";"; 219 System.out.println(arraySignature); 220 MethodHandle fromExecStackToValueArray = MethodHandleBuilder.loadCode( 221 LOOKUP, 222 "execStackToValueArray", 223 MethodType.methodType(boolean.class), 224 CODE -> { 225 CODE 226 .invokestatic(System.class, "gc", "()V", false) 227 .new_(containerClass) 228 .dup() 229 .invoke(MacroCodeBuilder.InvocationKind.INVOKESPECIAL, containerClass, "<init>", "()V", false) 230 .astore_1() 231 .ldc(ITERATIONS * 3) 232 .anewarray(inlineClass) 233 .astore_2() 234 .aload_2() 235 .aload_1() 236 .swap() 237 .putfield(containerClass, "valueArray", arraySignature) 238 .iconst_0() 239 .istore_3() 240 .label("loop1") 241 .iload_3() 242 .ldc(ITERATIONS) 243 .ifcmp(TypeTag.I, CondKind.GE, "end1") 244 .aload_2() 245 .iload_3() 246 .invokestatic(inlineClass, "getInstance", signature, false) 247 .aastore() 248 .iinc(3, 1) 249 .aload_2() 250 .iload_3() 251 .invokestatic(inlineClass, "getNonBufferedInstance", signature, false) 252 .aastore() 253 .iinc(3, 1) 254 .aload_2() 255 .iload_3() 256 .defaultvalue(inlineClass) 257 .aastore() 258 .iinc(3, 1) 259 .goto_("loop1") 260 .label("end1") 261 .invokestatic(System.class, "gc", "()V", false) 262 .iconst_0() 263 .istore_3() 264 .label("loop2") 265 .iload_3() 266 .ldc(ITERATIONS * 3) 267 .ifcmp(TypeTag.I, CondKind.GE, "end2") 268 .aload_2() 269 .iload_3() 270 .aaload() 271 .invokevirtual(inlineClass, "verify", "()Z", false) 272 .iconst_1() 273 .ifcmp(TypeTag.I, CondKind.NE, "failed") 274 .iinc(3, 1) 275 .goto_("loop2") 276 .label("end2") 277 .iconst_1() 278 .return_(TypeTag.Z) 279 .label("failed") 280 .iconst_0() 281 .return_(TypeTag.Z); 282 }); 283 boolean result = (boolean) fromExecStackToValueArray.invokeExact(); 284 System.out.println(result); 285 assertTrue(result, "Invariant"); 286 } 287 }