25 package compiler.jvmci.compilerToVM; |
25 package compiler.jvmci.compilerToVM; |
26 |
26 |
27 import java.util.HashMap; |
27 import java.util.HashMap; |
28 import java.util.Map; |
28 import java.util.Map; |
29 import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; |
29 import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; |
30 import jdk.internal.misc.SharedSecrets; |
30 import sun.hotspot.WhiteBox; |
31 import sun.reflect.ConstantPool; |
31 import sun.reflect.ConstantPool; |
|
32 import sun.reflect.ConstantPool.Tag; |
|
33 import compiler.jvmci.compilerToVM.ConstantPoolTestsHelper.DummyClasses; |
|
34 import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.*; |
32 |
35 |
33 /** |
36 /** |
34 * Common class for jdk.vm.ci.hotspot.CompilerToVM constant pool tests |
37 * Common class for jdk.vm.ci.hotspot.CompilerToVM constant pool tests |
35 */ |
38 */ |
36 public class ConstantPoolTestCase { |
39 public class ConstantPoolTestCase { |
37 private final Map<ConstantPoolTestsHelper.ConstantTypes, Validator> typeTests; |
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 } |
38 |
175 |
39 public static interface Validator { |
176 public static interface Validator { |
40 void validate(jdk.vm.ci.meta.ConstantPool constantPoolCTVM, |
177 void validate(jdk.vm.ci.meta.ConstantPool constantPoolCTVM, |
41 ConstantPool constantPoolSS, |
178 ConstantTypes cpType, |
42 ConstantPoolTestsHelper.DummyClasses dummyClass, int index); |
179 DummyClasses dummyClass, |
43 } |
180 int index); |
44 |
181 } |
45 public ConstantPoolTestCase(Map<ConstantPoolTestsHelper.ConstantTypes,Validator> typeTests) { |
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) { |
46 this.typeTests = new HashMap<>(); |
217 this.typeTests = new HashMap<>(); |
47 this.typeTests.putAll(typeTests); |
218 this.typeTests.putAll(typeTests); |
48 } |
219 } |
49 |
220 |
50 private void messageOnFail(Throwable t, |
|
51 ConstantPoolTestsHelper.ConstantTypes cpType, |
|
52 ConstantPoolTestsHelper.DummyClasses dummyClass, int index) { |
|
53 ConstantPool constantPoolSS = SharedSecrets.getJavaLangAccess(). |
|
54 getConstantPool(dummyClass.klass); |
|
55 String msg = String.format("Test for %s constant pool entry of" |
|
56 + " type %s", |
|
57 dummyClass.klass, cpType.name()); |
|
58 switch (cpType) { |
|
59 case CONSTANT_CLASS: |
|
60 case CONSTANT_STRING: |
|
61 case CONSTANT_METHODTYPE: |
|
62 String utf8 = constantPoolSS |
|
63 .getUTF8At((int) dummyClass.cp.get(index).value); |
|
64 msg = String.format("%s (%s) failed with %s", msg, utf8, t); |
|
65 break; |
|
66 case CONSTANT_INTEGER: |
|
67 int intValue = constantPoolSS.getIntAt(index); |
|
68 msg = String.format("%s (%d) failed with %s", msg, intValue, t); |
|
69 break; |
|
70 case CONSTANT_LONG: |
|
71 long longValue = constantPoolSS.getLongAt(index); |
|
72 msg = String.format("%s (%d) failed with %s", msg, longValue, t); |
|
73 break; |
|
74 case CONSTANT_FLOAT: |
|
75 float floatValue = constantPoolSS.getFloatAt(index); |
|
76 msg = String.format("%s (%E) failed with %s", msg, floatValue, t); |
|
77 break; |
|
78 case CONSTANT_DOUBLE: |
|
79 double doubleValue = constantPoolSS.getDoubleAt(index); |
|
80 msg = String.format("%s (%E) failed with %s", msg, doubleValue, t); |
|
81 break; |
|
82 case CONSTANT_UTF8: |
|
83 String utf8Value = constantPoolSS.getUTF8At(index); |
|
84 msg = String.format("%s (%s) failed with %s", msg, utf8Value, t); |
|
85 break; |
|
86 case CONSTANT_INVOKEDYNAMIC: |
|
87 index = ((int[]) dummyClass.cp.get(index).value)[1]; |
|
88 case CONSTANT_NAMEANDTYPE: |
|
89 String name = constantPoolSS |
|
90 .getUTF8At(((int[]) dummyClass.cp.get(index).value)[0]); |
|
91 String type = constantPoolSS |
|
92 .getUTF8At(((int[]) dummyClass.cp.get(index).value)[1]); |
|
93 msg = String.format("%s (%s:%s) failed with %s", |
|
94 msg, name, type, t); |
|
95 break; |
|
96 case CONSTANT_METHODHANDLE: |
|
97 index = ((int[]) dummyClass.cp.get(index).value)[1]; |
|
98 case CONSTANT_METHODREF: |
|
99 case CONSTANT_INTERFACEMETHODREF: |
|
100 case CONSTANT_FIELDREF: |
|
101 int classIndex = ((int[]) dummyClass.cp.get(index).value)[0]; |
|
102 int nameAndTypeIndex = ((int[]) dummyClass.cp.get(index).value)[1]; |
|
103 String cName = constantPoolSS |
|
104 .getUTF8At((int) dummyClass.cp.get(classIndex).value); |
|
105 String mName = constantPoolSS |
|
106 .getUTF8At(((int[]) dummyClass.cp.get(nameAndTypeIndex).value)[0]); |
|
107 String mType = constantPoolSS |
|
108 .getUTF8At(((int[]) dummyClass.cp.get(nameAndTypeIndex).value)[1]); |
|
109 msg = String.format("%s (%s.%s:%s) failed with %s ", |
|
110 msg, cName, mName, mType, t); |
|
111 break; |
|
112 default: |
|
113 msg = String.format("Test bug: unknown constant type %s ", cpType); |
|
114 } |
|
115 throw new Error(msg + t.getMessage(), t); |
|
116 } |
|
117 |
|
118 public void test() { |
221 public void test() { |
119 for (ConstantPoolTestsHelper.DummyClasses dummyClass |
222 for (DummyClasses dummyClass : DummyClasses.values()) { |
120 : ConstantPoolTestsHelper.DummyClasses.values()) { |
223 boolean isCPCached = WB.getConstantPoolCacheLength(dummyClass.klass) > -1; |
121 System.out.printf("%nTesting dummy %s%n", dummyClass.klass); |
224 System.out.printf("Testing dummy %s with constant pool cached = %b%n", |
122 HotSpotResolvedObjectType holder = HotSpotResolvedObjectType |
225 dummyClass.klass, |
123 .fromObjectClass(dummyClass.klass); |
226 isCPCached); |
124 jdk.vm.ci.meta.ConstantPool constantPoolCTVM |
227 HotSpotResolvedObjectType holder = HotSpotResolvedObjectType.fromObjectClass(dummyClass.klass); |
125 = holder.getConstantPool(); |
228 jdk.vm.ci.meta.ConstantPool constantPoolCTVM = holder.getConstantPool(); |
126 ConstantPool constantPoolSS = SharedSecrets.getJavaLangAccess(). |
229 ConstantPool constantPoolSS = dummyClass.constantPoolSS; |
127 getConstantPool(dummyClass.klass); |
230 for (int i = 0; i < constantPoolSS.getSize(); i++) { |
128 for (Integer i : dummyClass.cp.keySet()) { |
231 Tag tag = constantPoolSS.getTagAt(i); |
129 ConstantPoolTestsHelper.ConstantTypes cpType |
232 ConstantTypes cpType = mapTagToCPType(tag); |
130 = dummyClass.cp.get(i).type; |
|
131 if (!typeTests.keySet().contains(cpType)) { |
233 if (!typeTests.keySet().contains(cpType)) { |
132 continue; |
234 continue; |
133 } |
235 } |
134 try { |
236 typeTests.get(cpType).validate(constantPoolCTVM, cpType, dummyClass, i); |
135 typeTests.get(cpType).validate(constantPoolCTVM, |
|
136 constantPoolSS, dummyClass, i); |
|
137 } catch (Throwable t) { |
|
138 messageOnFail(t, cpType, dummyClass, i); |
|
139 } |
|
140 } |
237 } |
141 } |
238 } |
142 } |
239 } |
143 } |
240 } |
144 |
|