1 /* 2 * Copyright (c) 2010, 2016, 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 6991980 27 * @summary polymorphic signature calls don't share the same CP entries 28 * @modules jdk.jdeps/com.sun.tools.classfile 29 * @run main TestCP 30 */ 31 32 import com.sun.tools.classfile.Instruction; 33 import com.sun.tools.classfile.Attribute; 34 import com.sun.tools.classfile.ClassFile; 35 import com.sun.tools.classfile.Code_attribute; 36 import com.sun.tools.classfile.ConstantPool.*; 37 import com.sun.tools.classfile.Method; 38 39 import java.lang.invoke.*; 40 import java.io.*; 41 42 public class TestCP { 43 44 static class TestMethodHandleInvokeExact { 45 static final String PS_TYPE = "(Ljava/lang/String;IC)Ljava/lang/Number;"; 46 test(MethodHandle mh)47 void test(MethodHandle mh) throws Throwable { 48 Number n = (Number)mh.invokeExact("daddy",1,'n'); 49 n = (Number)mh.invokeExact("bunny",1,'d'); 50 n = (Number)(mh.invokeExact("foo",1,'d')); 51 n = (Number)((mh.invokeExact("bar",1,'d'))); 52 } 53 } 54 55 static class TestVarHandleGet { 56 static final String PS_TYPE = "(Ljava/lang/String;IC)Ljava/lang/Number;"; 57 58 // Test with sig-poly return type test(VarHandle vh)59 void test(VarHandle vh) throws Throwable { 60 Number n = (Number)vh.get("daddy",1,'n'); 61 n = (Number)vh.get("bunny",1,'d'); 62 n = (Number)(vh.get("foo",1,'d')); 63 n = (Number)((vh.get("bar",1,'d'))); 64 } 65 } 66 67 static class TestVarHandleSet { 68 static final String PS_TYPE = "(Ljava/lang/String;IC)V"; 69 70 // Test with non-sig-poly void return type test(VarHandle vh)71 void test(VarHandle vh) throws Throwable { 72 vh.set("daddy",1,'n'); 73 vh.set("bunny",1,'d'); 74 vh.set("foo",1,'d'); 75 vh.set("bar",1,'d'); 76 } 77 } 78 79 static class TestVarHandleCompareAndSet { 80 static final String PS_TYPE = "(Ljava/lang/String;IC)Z"; 81 82 // Test with non-sig-poly boolean return type test(VarHandle vh)83 void test(VarHandle vh) throws Throwable { 84 boolean r = vh.compareAndSet("daddy",1,'n'); 85 r = vh.compareAndSet("bunny",1,'d'); 86 r = (vh.compareAndSet("foo",1,'d')); 87 r = ((vh.compareAndSet("bar",1,'d'))); 88 } 89 } 90 91 static final int PS_CALLS_COUNT = 4; 92 static final String TEST_METHOD_NAME = "test"; 93 main(String... args)94 public static void main(String... args) throws Exception { 95 new TestCP().run(); 96 } 97 run()98 public void run() throws Exception { 99 verifySigPolyInvokeVirtual( 100 getTestFile(TestMethodHandleInvokeExact.class), 101 TestMethodHandleInvokeExact.PS_TYPE); 102 103 verifySigPolyInvokeVirtual( 104 getTestFile(TestVarHandleGet.class), 105 TestVarHandleGet.PS_TYPE); 106 107 verifySigPolyInvokeVirtual( 108 getTestFile(TestVarHandleSet.class), 109 TestVarHandleSet.PS_TYPE); 110 111 verifySigPolyInvokeVirtual( 112 getTestFile(TestVarHandleCompareAndSet.class), 113 TestVarHandleCompareAndSet.PS_TYPE); 114 } 115 getTestFile(Class<?> c)116 static File getTestFile(Class<?> c) { 117 String workDir = System.getProperty("test.classes"); 118 return new File(workDir, getTestName(c)); 119 } getTestName(Class<?> c)120 static String getTestName(Class<?> c) { 121 return c.getName() + ".class"; 122 } 123 verifySigPolyInvokeVirtual(File f, String psType)124 void verifySigPolyInvokeVirtual(File f, String psType) { 125 System.err.println("verify: " + f); 126 try { 127 int count = 0; 128 ClassFile cf = ClassFile.read(f); 129 Method testMethod = null; 130 for (Method m : cf.methods) { 131 if (m.getName(cf.constant_pool).equals(TEST_METHOD_NAME)) { 132 testMethod = m; 133 break; 134 } 135 } 136 if (testMethod == null) { 137 throw new Error("Test method not found"); 138 } 139 Code_attribute ea = (Code_attribute)testMethod.attributes.get(Attribute.Code); 140 if (testMethod == null) { 141 throw new Error("Code attribute for test() method not found"); 142 } 143 int instr_count = 0; 144 int cp_entry = -1; 145 146 for (Instruction i : ea.getInstructions()) { 147 if (i.getMnemonic().equals("invokevirtual")) { 148 instr_count++; 149 if (cp_entry == -1) { 150 cp_entry = i.getUnsignedShort(1); 151 } else if (cp_entry != i.getUnsignedShort(1)) { 152 throw new Error("Unexpected CP entry in polymorphic signature call"); 153 } 154 CONSTANT_Methodref_info methRef = 155 (CONSTANT_Methodref_info)cf.constant_pool.get(cp_entry); 156 String type = methRef.getNameAndTypeInfo().getType(); 157 if (!type.equals(psType)) { 158 throw new Error("Unexpected type in polymorphic signature call: " + type); 159 } 160 } 161 } 162 if (instr_count != PS_CALLS_COUNT) { 163 throw new Error("Wrong number of polymorphic signature call found: " + instr_count); 164 } 165 } catch (Exception e) { 166 e.printStackTrace(); 167 throw new Error("error reading " + f +": " + e); 168 } 169 } 170 } 171