1 /* 2 * Copyright (c) 2015, 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 package compiler.jvmci.compilerToVM; 26 27 import compiler.jvmci.compilerToVM.ConstantPoolTestsHelper.DummyClasses; 28 import jdk.internal.reflect.ConstantPool; 29 import jdk.internal.reflect.ConstantPool.Tag; 30 import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; 31 import jdk.vm.ci.meta.ResolvedJavaMethod; 32 import sun.hotspot.WhiteBox; 33 34 import java.util.HashMap; 35 import java.util.Map; 36 37 import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.CONSTANT_CLASS; 38 import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.CONSTANT_DOUBLE; 39 import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.CONSTANT_FIELDREF; 40 import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.CONSTANT_FLOAT; 41 import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.CONSTANT_INTEGER; 42 import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.CONSTANT_INTERFACEMETHODREF; 43 import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.CONSTANT_INVALID; 44 import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.CONSTANT_INVOKEDYNAMIC; 45 import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.CONSTANT_LONG; 46 import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.CONSTANT_METHODHANDLE; 47 import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.CONSTANT_METHODREF; 48 import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.CONSTANT_METHODTYPE; 49 import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.CONSTANT_NAMEANDTYPE; 50 import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.CONSTANT_STRING; 51 import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.CONSTANT_UTF8; 52 53 /** 54 * Common class for jdk.vm.ci.hotspot.CompilerToVM constant pool tests 55 */ 56 public class ConstantPoolTestCase { 57 58 private static final Map<Tag, ConstantTypes> TAG_TO_TYPE_MAP; 59 static { 60 TAG_TO_TYPE_MAP = new HashMap<>(); 61 TAG_TO_TYPE_MAP.put(Tag.CLASS, CONSTANT_CLASS); 62 TAG_TO_TYPE_MAP.put(Tag.FIELDREF, CONSTANT_FIELDREF); 63 TAG_TO_TYPE_MAP.put(Tag.METHODREF, CONSTANT_METHODREF); 64 TAG_TO_TYPE_MAP.put(Tag.INTERFACEMETHODREF, CONSTANT_INTERFACEMETHODREF); 65 TAG_TO_TYPE_MAP.put(Tag.STRING, CONSTANT_STRING); 66 TAG_TO_TYPE_MAP.put(Tag.INTEGER, CONSTANT_INTEGER); 67 TAG_TO_TYPE_MAP.put(Tag.FLOAT, CONSTANT_FLOAT); 68 TAG_TO_TYPE_MAP.put(Tag.LONG, CONSTANT_LONG); 69 TAG_TO_TYPE_MAP.put(Tag.DOUBLE, CONSTANT_DOUBLE); 70 TAG_TO_TYPE_MAP.put(Tag.NAMEANDTYPE, CONSTANT_NAMEANDTYPE); 71 TAG_TO_TYPE_MAP.put(Tag.UTF8, CONSTANT_UTF8); 72 TAG_TO_TYPE_MAP.put(Tag.METHODHANDLE, CONSTANT_METHODHANDLE); 73 TAG_TO_TYPE_MAP.put(Tag.METHODTYPE, CONSTANT_METHODTYPE); 74 TAG_TO_TYPE_MAP.put(Tag.INVOKEDYNAMIC, CONSTANT_INVOKEDYNAMIC); 75 TAG_TO_TYPE_MAP.put(Tag.INVALID, CONSTANT_INVALID); 76 } 77 private static final WhiteBox WB = WhiteBox.getWhiteBox(); 78 private final Map<ConstantTypes, Validator> typeTests; 79 80 public static enum ConstantTypes { 81 CONSTANT_CLASS { 82 @Override 83 public TestedCPEntry getTestedCPEntry(DummyClasses dummyClass, int index) { 84 ConstantPool constantPoolSS = dummyClass.constantPoolSS; 85 checkIndex(constantPoolSS, index); 86 Class<?> klass = constantPoolSS.getClassAt(index); 87 String klassName = klass.getName(); 88 TestedCPEntry[] testedEntries = dummyClass.testedCP.get(this); 89 for (TestedCPEntry entry : testedEntries) { 90 if (entry.klass.replaceAll("/", "\\.").equals(klassName)) { 91 return entry; 92 } 93 } 94 return null; 95 } 96 }, 97 CONSTANT_FIELDREF { 98 @Override 99 public TestedCPEntry getTestedCPEntry(DummyClasses dummyClass, int index) { 100 return this.getTestedCPEntryForMethodAndField(dummyClass, index); 101 } 102 }, 103 CONSTANT_METHODREF { 104 @Override 105 public TestedCPEntry getTestedCPEntry(DummyClasses dummyClass, int index) { 106 return this.getTestedCPEntryForMethodAndField(dummyClass, index); 107 } 108 }, 109 CONSTANT_INTERFACEMETHODREF { 110 @Override 111 public TestedCPEntry getTestedCPEntry(DummyClasses dummyClass, int index) { 112 return this.getTestedCPEntryForMethodAndField(dummyClass, index); 113 } 114 }, 115 CONSTANT_STRING { 116 @Override 117 public TestedCPEntry getTestedCPEntry(DummyClasses dummyClass, int index) { 118 ConstantPool constantPoolSS = dummyClass.constantPoolSS; 119 checkIndex(constantPoolSS, index); 120 String value = constantPoolSS.getStringAt(index); 121 TestedCPEntry[] testedEntries = dummyClass.testedCP.get(this); 122 for (TestedCPEntry entry : testedEntries) { 123 if (entry.name.equals(value)) { 124 return entry; 125 } 126 } 127 return null; 128 } 129 }, 130 CONSTANT_INTEGER, 131 CONSTANT_FLOAT, 132 CONSTANT_LONG, 133 CONSTANT_DOUBLE, 134 CONSTANT_NAMEANDTYPE, 135 CONSTANT_UTF8, 136 CONSTANT_METHODHANDLE, 137 CONSTANT_METHODTYPE, 138 CONSTANT_INVOKEDYNAMIC { 139 @Override 140 public TestedCPEntry getTestedCPEntry(DummyClasses dummyClass, int index) { 141 ConstantPool constantPoolSS = dummyClass.constantPoolSS; 142 checkIndex(constantPoolSS, index); 143 int nameAndTypeIndex = constantPoolSS.getNameAndTypeRefIndexAt(index); 144 String[] info = constantPoolSS.getNameAndTypeRefInfoAt(nameAndTypeIndex); 145 TestedCPEntry[] testedEntries = dummyClass.testedCP.get(this); 146 for (TestedCPEntry entry : testedEntries) { 147 if (info[0].equals(entry.name) && info[1].equals(entry.type)) { 148 return entry; 149 } 150 } 151 return null; 152 } 153 }, 154 CONSTANT_INVALID; 155 156 public TestedCPEntry getTestedCPEntry(DummyClasses dummyClass, int index) { 157 return null; // returning null by default 158 } 159 160 public TestedCPEntry[] getAllCPEntriesForType(DummyClasses dummyClass) { 161 TestedCPEntry[] toReturn = dummyClass.testedCP.get(this); 162 if (toReturn == null) { 163 return new TestedCPEntry[0]; 164 } 165 return dummyClass.testedCP.get(this); 166 } 167 168 protected TestedCPEntry getTestedCPEntryForMethodAndField(DummyClasses dummyClass, int index) { 169 ConstantPool constantPoolSS = dummyClass.constantPoolSS; 170 checkIndex(constantPoolSS, index); 171 String[] info = constantPoolSS.getMemberRefInfoAt(index); 172 TestedCPEntry[] testedEntries = dummyClass.testedCP.get(this); 173 for (TestedCPEntry entry : testedEntries) { 174 if (info[0].equals(entry.klass) && info[1].equals(entry.name) && info[2].equals(entry.type)) { 175 return entry; 176 } 177 } 178 return null; 179 } 180 181 protected void checkIndex(ConstantPool constantPoolSS, int index) { 182 ConstantPool.Tag tag = constantPoolSS.getTagAt(index); 183 ConstantTypes type = mapTagToCPType(tag); 184 if (!this.equals(type)) { 185 String msg = String.format("TESTBUG: CP tag should be a %s, but is %s", 186 this.name(), 187 type.name()); 188 throw new Error(msg); 189 } 190 } 191 } 192 193 public static interface Validator { 194 void validate(jdk.vm.ci.meta.ConstantPool constantPoolCTVM, 195 ConstantTypes cpType, 196 DummyClasses dummyClass, 197 int index); 198 } 199 200 public static class TestedCPEntry { 201 public final String klass; 202 public final String name; 203 public final String type; 204 public final ResolvedJavaMethod[] methods; 205 public final byte[] opcodes; 206 public final long accFlags; 207 208 public TestedCPEntry(String klass, String name, String type, byte[] opcodes, long accFlags) { 209 this(klass, name, type, null, opcodes, accFlags); 210 } 211 212 public TestedCPEntry(String klass, String name, String type, ResolvedJavaMethod[] methods, byte[] opcodes, long accFlags) { 213 this.klass = klass; 214 this.name = name; 215 this.type = type; 216 if (methods != null) { 217 this.methods = new ResolvedJavaMethod[methods.length]; 218 System.arraycopy(methods, 0, this.methods, 0, methods.length); 219 } else { 220 this.methods = null; 221 } 222 if (opcodes != null) { 223 this.opcodes = new byte[opcodes.length]; 224 System.arraycopy(opcodes, 0, this.opcodes, 0, opcodes.length); 225 } else { 226 this.opcodes = null; 227 } 228 this.accFlags = accFlags; 229 } 230 231 public TestedCPEntry(String klass, String name, String type, byte[] opcodes) { 232 this(klass, name, type, opcodes, 0); 233 } 234 235 public TestedCPEntry(String klass, String name, String type) { 236 this(klass, name, type, null, 0); 237 } 238 } 239 240 public static ConstantTypes mapTagToCPType(Tag tag) { 241 return TAG_TO_TYPE_MAP.get(tag); 242 } 243 244 public ConstantPoolTestCase(Map<ConstantTypes, Validator> typeTests) { 245 this.typeTests = new HashMap<>(); 246 this.typeTests.putAll(typeTests); 247 } 248 249 public void test() { 250 for (DummyClasses dummyClass : DummyClasses.values()) { 251 boolean isCPCached = WB.getConstantPoolCacheLength(dummyClass.klass) > -1; 252 System.out.printf("Testing dummy %s with constant pool cached = %b%n", 253 dummyClass.klass, 254 isCPCached); 255 HotSpotResolvedObjectType holder = HotSpotResolvedObjectType.fromObjectClass(dummyClass.klass); 256 jdk.vm.ci.meta.ConstantPool constantPoolCTVM = holder.getConstantPool(); 257 ConstantPool constantPoolSS = dummyClass.constantPoolSS; 258 for (int i = 0; i < constantPoolSS.getSize(); i++) { 259 Tag tag = constantPoolSS.getTagAt(i); 260 ConstantTypes cpType = mapTagToCPType(tag); 261 if (!typeTests.keySet().contains(cpType)) { 262 continue; 263 } 264 typeTests.get(cpType).validate(constantPoolCTVM, cpType, dummyClass, i); 265 } 266 } 267 } 268 }