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 * @test 26 * @bug 8186046 27 * @summary Stress test ldc to ensure HotSpot correctly manages oop maps 28 * @library /lib/testlibrary/bytecode /java/lang/invoke/common 29 * @build jdk.experimental.bytecode.BasicClassBuilder test.java.lang.invoke.lib.InstructionHelper 30 * @run testng CondyWithGarbageTest 31 * @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 CondyWithGarbageTest 32 */ 33 34 35 import jdk.experimental.bytecode.BasicClassBuilder; 36 import jdk.experimental.bytecode.Flag; 37 import jdk.experimental.bytecode.TypedCodeBuilder; 38 import org.testng.Assert; 39 import org.testng.annotations.Test; 40 41 import java.lang.invoke.MethodHandle; 42 import java.lang.invoke.MethodHandles; 43 44 import static java.lang.invoke.MethodType.methodType; 45 import static test.java.lang.invoke.lib.InstructionHelper.cref; 46 import static test.java.lang.invoke.lib.InstructionHelper.csym; 47 48 public class CondyWithGarbageTest { 49 static final MethodHandles.Lookup L = MethodHandles.lookup(); 50 51 @Test testString()52 public void testString() throws Throwable { 53 MethodHandle mh = lcdStringBasher(); 54 int l = 0; 55 for (int i = 0; i < 100000; i++) { 56 l += +((String) mh.invoke()).length(); 57 } 58 Assert.assertTrue(l > 0); 59 } 60 bsmString(MethodHandles.Lookup l, String constantName, Class<?> constantType)61 public static Object bsmString(MethodHandles.Lookup l, 62 String constantName, 63 Class<?> constantType) { 64 return new StringBuilder(constantName).toString(); 65 } 66 lcdStringBasher()67 static MethodHandle lcdStringBasher() throws Exception { 68 byte[] byteArray = new BasicClassBuilder(csym(L.lookupClass()) + "$Code$String", 55, 0) 69 .withSuperclass("java/lang/Object") 70 .withMethod("<init>", "()V", M -> 71 M.withFlags(Flag.ACC_PUBLIC) 72 .withCode(TypedCodeBuilder::new, C -> 73 C.aload_0().invokespecial("java/lang/Object", "<init>", "()V", false).return_() 74 )) 75 .withMethod("m", "()" + cref(String.class), M -> 76 M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) 77 .withCode(TypedCodeBuilder::new, C -> { 78 C.new_(csym(StringBuilder.class)) 79 .dup() 80 .invokespecial(csym(StringBuilder.class), "<init>", "()V", false) 81 .astore_0(); 82 83 for (int i = 10; i < 100; i++) { 84 ldcString(C, Integer.toString(i)); 85 C.astore_1().aload_0().aload_1(); 86 C.invokevirtual(csym(StringBuilder.class), "append", methodType(StringBuilder.class, String.class).toMethodDescriptorString(), false); 87 C.pop(); 88 } 89 90 C.aload_0(); 91 C.invokevirtual(csym(StringBuilder.class), "toString", methodType(String.class).toMethodDescriptorString(), false); 92 C.areturn(); 93 } 94 )) 95 .build(); 96 97 Class<?> gc = L.defineClass(byteArray); 98 return L.findStatic(gc, "m", methodType(String.class)); 99 } 100 ldcString(TypedCodeBuilder<String, String, byte[], ?> C, String name)101 static void ldcString(TypedCodeBuilder<String, String, byte[], ?> C, String name) { 102 C.ldc(name, cref(String.class), 103 csym(L.lookupClass()), 104 "bsmString", 105 methodType(Object.class, MethodHandles.Lookup.class, String.class, Class.class).toMethodDescriptorString(), 106 S -> { 107 }); 108 } 109 110 111 @Test testStringArray()112 public void testStringArray() throws Throwable { 113 MethodHandle mh = lcdStringArrayBasher(); 114 int l = 0; 115 for (int i = 0; i < 100000; i++) { 116 l += +((String) mh.invoke()).length(); 117 } 118 Assert.assertTrue(l > 0); 119 } 120 bsmStringArray(MethodHandles.Lookup l, String constantName, Class<?> constantType)121 public static Object bsmStringArray(MethodHandles.Lookup l, 122 String constantName, 123 Class<?> constantType) { 124 return new String[]{new StringBuilder(constantName).toString()}; 125 } 126 lcdStringArrayBasher()127 static MethodHandle lcdStringArrayBasher() throws Exception { 128 byte[] byteArray = new BasicClassBuilder(csym(L.lookupClass()) + "$Code$StringArray", 55, 0) 129 .withSuperclass("java/lang/Object") 130 .withMethod("<init>", "()V", M -> 131 M.withFlags(Flag.ACC_PUBLIC) 132 .withCode(TypedCodeBuilder::new, C -> 133 C.aload_0().invokespecial("java/lang/Object", "<init>", "()V", false).return_() 134 )) 135 .withMethod("m", "()" + cref(String.class), M -> 136 M.withFlags(Flag.ACC_PUBLIC, Flag.ACC_STATIC) 137 .withCode(TypedCodeBuilder::new, C -> { 138 C.new_(csym(StringBuilder.class)) 139 .dup() 140 .invokespecial(csym(StringBuilder.class), "<init>", "()V", false) 141 .astore_0(); 142 143 for (int i = 10; i < 100; i++) { 144 ldcStringArray(C, Integer.toString(i)); 145 C.bipush(0).aaload().astore_1(); 146 C.aload_0().aload_1(); 147 C.invokevirtual(csym(StringBuilder.class), "append", methodType(StringBuilder.class, String.class).toMethodDescriptorString(), false); 148 C.pop(); 149 } 150 151 C.aload_0(); 152 C.invokevirtual(csym(StringBuilder.class), "toString", methodType(String.class).toMethodDescriptorString(), false); 153 C.areturn(); 154 } 155 )) 156 .build(); 157 158 Class<?> gc = L.defineClass(byteArray); 159 return L.findStatic(gc, "m", methodType(String.class)); 160 } 161 ldcStringArray(TypedCodeBuilder<String, String, byte[], ?> C, String name)162 static void ldcStringArray(TypedCodeBuilder<String, String, byte[], ?> C, String name) { 163 C.ldc(name, cref(String[].class), 164 csym(L.lookupClass()), 165 "bsmStringArray", 166 methodType(Object.class, MethodHandles.Lookup.class, String.class, Class.class).toMethodDescriptorString(), 167 S -> { 168 }); 169 } 170 } 171