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