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 */ 66 public class ValueTypesTest { 67 68 public static void main(String[] args) { 69 Class<?> inlineClass = runtime.valhalla.valuetypes.TestValue1.class; 70 Class<?> testClasses[] = { 71 runtime.valhalla.valuetypes.TestValue1.class, 72 runtime.valhalla.valuetypes.TestValue2.class, 73 runtime.valhalla.valuetypes.TestValue3.class, 74 runtime.valhalla.valuetypes.TestValue4.class 75 }; 76 Class<?> containerClasses[] = { 77 runtime.valhalla.valuetypes.ContainerValue1.class, 78 runtime.valhalla.valuetypes.ContainerValue2.class, 79 runtime.valhalla.valuetypes.ContainerValue3.class, 80 runtime.valhalla.valuetypes.ContainerValue4.class 81 }; 82 83 for (int i = 0; i < testClasses.length; i++) { 84 try { 85 testExecutionStackToLocalVariable(testClasses[i]); 86 testExecutionStackToFields(testClasses[i], containerClasses[i]); 87 // testExecutionStackToValueArray(testClasses[i], containerClasses[i]); 88 } catch (Throwable t) { 89 t.printStackTrace(); 90 throw new RuntimeException(t); 91 } 92 } 93 } 94 95 static MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); 96 97 static void testExecutionStackToLocalVariable(Class<?> inlineClass) throws Throwable { 98 String sig = "()Q" + inlineClass.getName() + ";"; 99 final String signature = sig.replace('.', '/'); 100 MethodHandle fromExecStackToLocalVar = MethodHandleBuilder.loadCode( 101 LOOKUP, 102 "execStackToLocalVar", 103 MethodType.methodType(boolean.class), 104 CODE -> { 105 CODE.invokestatic(System.class, "gc", "()V", false); 106 int n = -1; 107 while (n < 1024) { 108 n++; 109 CODE 110 .invokestatic(inlineClass, "getInstance", signature, false) 111 .astore(n); 112 n++; 113 CODE 114 .invokestatic(inlineClass, "getNonBufferedInstance", signature, false) 115 .astore(n); 116 } 117 CODE.invokestatic(System.class, "gc", "()V", false); 118 while (n > 0) { 119 CODE 120 .aload(n) 121 .invokevirtual(inlineClass, "verify", "()Z", false) 122 .iconst_1() 123 .ifcmp(TypeTag.I, CondKind.NE, "end"); 124 n--; 125 } 126 CODE 127 .iconst_1() 128 .return_(TypeTag.Z) 129 .label("end") 130 .iconst_0() 131 .return_(TypeTag.Z); 132 }); 133 boolean result = (boolean) fromExecStackToLocalVar.invokeExact(); 134 System.out.println(result); 135 assertTrue(result, "Invariant"); 136 } 137 138 static void testExecutionStackToFields(Class<?> inlineClass, Class<?> containerClass) throws Throwable { 139 final int ITERATIONS = Platform.isDebugBuild() ? 3 : 512; 140 String sig = "()Q" + inlineClass.getName() + ";"; 141 final String methodSignature = sig.replace('.', '/'); 142 final String fieldQSignature = "Q" + inlineClass.getName().replace('.', '/') + ";"; 143 final String fieldLSignature = "L" + inlineClass.getName().replace('.', '/') + ";"; 144 System.out.println(methodSignature); 145 MethodHandle fromExecStackToFields = MethodHandleBuilder.loadCode( 146 LOOKUP, 147 "execStackToFields", 148 MethodType.methodType(boolean.class), 149 CODE -> { 150 CODE 151 .invokestatic(System.class, "gc", "()V", false) 152 .new_(containerClass) 153 .dup() 154 .invoke(MacroCodeBuilder.InvocationKind.INVOKESPECIAL, containerClass, "<init>", "()V", false) 155 .astore_1() 156 .iconst_m1() 157 .istore_2() 158 .label("loop") 159 .iload_2() 160 .ldc(ITERATIONS) 161 .ifcmp(TypeTag.I, CondKind.EQ, "end") 162 .aload_1() 163 .invokestatic(inlineClass, "getInstance", methodSignature, false) 164 .putfield(containerClass, "nonStaticValueField", fieldQSignature) 165 .invokestatic(System.class, "gc", "()V", false) 166 .aload_1() 167 .getfield(containerClass, "nonStaticValueField", fieldQSignature) 168 .invokevirtual(inlineClass, "verify", "()Z", false) 169 .iconst_1() 170 .ifcmp(TypeTag.I, CondKind.NE, "failed") 171 .aload_1() 172 .invokestatic(inlineClass, "getNonBufferedInstance", methodSignature, false) 173 .putfield(containerClass, "nonStaticValueField", fieldQSignature) 174 .invokestatic(System.class, "gc", "()V", false) 175 .aload_1() 176 .getfield(containerClass, "nonStaticValueField", fieldQSignature) 177 .invokevirtual(inlineClass, "verify", "()Z", false) 178 .iconst_1() 179 .ifcmp(TypeTag.I, CondKind.NE, "failed") 180 .invokestatic(inlineClass, "getInstance", methodSignature, false) 181 .putstatic(containerClass, "staticValueField", fieldLSignature) 182 .invokestatic(System.class, "gc", "()V", false) 183 .getstatic(containerClass, "staticValueField", fieldLSignature) 184 .invokevirtual(inlineClass, "verify", "()Z", false) 185 .iconst_1() 186 .ifcmp(TypeTag.I, CondKind.NE, "failed") 187 .invokestatic(inlineClass, "getNonBufferedInstance", methodSignature, false) 188 .putstatic(containerClass, "staticValueField", fieldLSignature) 189 .invokestatic(System.class, "gc", "()V", false) 190 .getstatic(containerClass, "staticValueField", fieldLSignature) 191 .invokevirtual(inlineClass, "verify", "()Z", false) 192 .iconst_1() 193 .ifcmp(TypeTag.I, CondKind.NE, "failed") 194 .iinc(2, 1) 195 .goto_("loop") 196 .label("end") 197 .iconst_1() 198 .return_(TypeTag.Z) 199 .label("failed") 200 .iconst_0() 201 .return_(TypeTag.Z); 202 }); 203 boolean result = (boolean) fromExecStackToFields.invokeExact(); 204 System.out.println(result); 205 assertTrue(result, "Invariant"); 206 } 207 208 static void testExecutionStackToValueArray(Class<?> inlineClass, Class<?> containerClass) throws Throwable { 209 final int ITERATIONS = Platform.isDebugBuild() ? 3 : 100; 210 String sig = "()Q" + inlineClass.getName() + ";"; 211 final String signature = sig.replace('.', '/'); 212 final String arraySignature = "[L" + inlineClass.getName().replace('.', '/') + ";"; 213 System.out.println(arraySignature); 214 MethodHandle fromExecStackToValueArray = MethodHandleBuilder.loadCode( 215 LOOKUP, 216 "execStackToValueArray", 217 MethodType.methodType(boolean.class), 218 CODE -> { 219 CODE 220 .invokestatic(System.class, "gc", "()V", false) 221 .new_(containerClass) 222 .dup() 223 .invoke(MacroCodeBuilder.InvocationKind.INVOKESPECIAL, containerClass, "<init>", "()V", false) 224 .astore_1() 225 .ldc(ITERATIONS * 3) 226 .anewarray(inlineClass) 227 .astore_2() 228 .aload_2() 229 .aload_1() 230 .swap() 231 .putfield(containerClass, "valueArray", arraySignature) 232 .iconst_0() 233 .istore_3() 234 .label("loop1") 235 .iload_3() 236 .ldc(ITERATIONS) 237 .ifcmp(TypeTag.I, CondKind.GE, "end1") 238 .aload_2() 239 .iload_3() 240 .invokestatic(inlineClass, "getInstance", signature, false) 241 .aastore() 242 .iinc(3, 1) 243 .aload_2() 244 .iload_3() 245 .invokestatic(inlineClass, "getNonBufferedInstance", signature, false) 246 .aastore() 247 .iinc(3, 1) 248 .aload_2() 249 .iload_3() 250 .defaultvalue(inlineClass) 251 .aastore() 252 .iinc(3, 1) 253 .goto_("loop1") 254 .label("end1") 255 .invokestatic(System.class, "gc", "()V", false) 256 .iconst_0() 257 .istore_3() 258 .label("loop2") 259 .iload_3() 260 .ldc(ITERATIONS * 3) 261 .ifcmp(TypeTag.I, CondKind.GE, "end2") 262 .aload_2() 263 .iload_3() 264 .aaload() 265 .invokevirtual(inlineClass, "verify", "()Z", false) 266 .iconst_1() 267 .ifcmp(TypeTag.I, CondKind.NE, "failed") 268 .iinc(3, 1) 269 .goto_("loop2") 270 .label("end2") 271 .iconst_1() 272 .return_(TypeTag.Z) 273 .label("failed") 274 .iconst_0() 275 .return_(TypeTag.Z); 276 }); 277 boolean result = (boolean) fromExecStackToValueArray.invokeExact(); 278 System.out.println(result); 279 assertTrue(result, "Invariant"); 280 } 281 }