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