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