43 import java.util.NoSuchElementException; |
43 import java.util.NoSuchElementException; |
44 import java.util.Objects; |
44 import java.util.Objects; |
45 import java.util.function.Consumer; |
45 import java.util.function.Consumer; |
46 import jdk.vm.ci.hotspot.CompilerToVMHelper; |
46 import jdk.vm.ci.hotspot.CompilerToVMHelper; |
47 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; |
47 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; |
|
48 import jdk.vm.ci.hotspot.HotSpotVMConfigAccess; |
|
49 import jdk.vm.ci.hotspot.HotSpotVMConfigStore; |
48 import jdk.test.lib.Asserts; |
50 import jdk.test.lib.Asserts; |
49 import jdk.test.lib.Utils; |
51 import jdk.test.lib.Utils; |
50 import jdk.internal.misc.Unsafe; |
52 import jdk.internal.misc.Unsafe; |
51 |
53 |
52 public class InitializeConfigurationTest { |
54 public class InitializeConfigurationTest { |
53 private static final Unsafe UNSAFE = Utils.getUnsafe(); |
|
54 |
|
55 public static void main(String args[]) { |
55 public static void main(String args[]) { |
56 new InitializeConfigurationTest().runTest(generateTestCases()); |
56 new InitializeConfigurationTest().runTest(); |
57 } |
57 } |
58 |
58 |
59 private static List<TestCase> generateTestCases() { |
59 private void runTest() { |
60 List<TestCase> result = new ArrayList<>(); |
60 TestHotSpotVMConfig config = new TestHotSpotVMConfig(HotSpotJVMCIRuntime.runtime().getConfigStore()); |
61 result.add(new TestCase("CodeCache", "_high_bound", "address", |
61 Asserts.assertNE(config.codeCacheHighBound, 0L, "Got null address"); |
62 InitializeConfigurationTest::verifyLongIsNotZero)); |
62 Asserts.assertNE(config.stubRoutineJintArrayCopy, 0L, "Got null address"); |
63 result.add(new TestCase("StubRoutines", "_jint_arraycopy", "address", |
|
64 InitializeConfigurationTest::verifyLongIsNotZero)); |
|
65 return result; |
|
66 } |
63 } |
67 |
64 |
68 private static void verifyLongIsNotZero(Object o) { |
65 private static class TestHotSpotVMConfig extends HotSpotVMConfigAccess { |
69 Asserts.assertNotNull(o, "Got null value"); |
|
70 Asserts.assertEQ(o.getClass(), Long.class, "Unexpected value type"); |
|
71 Asserts.assertNE(o, 0L, "Got null address"); |
|
72 } |
|
73 |
66 |
74 private void runTest(List<TestCase> tcases) { |
67 private TestHotSpotVMConfig(HotSpotVMConfigStore store) { |
75 VMStructDataReader reader = new VMStructDataReader( |
68 super(store); |
76 CompilerToVMHelper.initializeConfiguration(HotSpotJVMCIRuntime.runtime().getConfig())); |
|
77 while (reader.hasNext()) { |
|
78 VMFieldData data = reader.next(); |
|
79 for (TestCase tcase : tcases) { |
|
80 tcase.check(data); |
|
81 } |
|
82 } |
|
83 // now check if all passed |
|
84 for (TestCase tcase: tcases) { |
|
85 Asserts.assertTrue(tcase.isFound(), "Case failed: " + tcase); |
|
86 } |
|
87 } |
|
88 |
|
89 private static class VMStructDataReader implements Iterator<VMFieldData> { |
|
90 // see jvmciCompilerToVM:105 static uintptr_t ciHotSpotVMData[28]; |
|
91 private static final int HOTSPOT_VM_DATA_INDEX_COUNT = 28; |
|
92 private final long addresses[]; |
|
93 private final long vmStructsBase; |
|
94 private final long entityNameFieldOffset; |
|
95 private final long nameFieldOffset; |
|
96 private final long typeStringFieldOffset; |
|
97 private final long addressOffset; |
|
98 private final long entrySize; |
|
99 private long nextElementAddress; |
|
100 private VMFieldData nextElement; |
|
101 |
|
102 public VMStructDataReader(long gHotSpotVMData) { |
|
103 Asserts.assertNE(gHotSpotVMData, 0L, "Got null base address"); |
|
104 addresses = new long[HOTSPOT_VM_DATA_INDEX_COUNT]; |
|
105 for (int i = 0; i < HOTSPOT_VM_DATA_INDEX_COUNT; i++) { |
|
106 addresses[i] = UNSAFE.getAddress( |
|
107 gHotSpotVMData + Unsafe.ADDRESS_SIZE * i); |
|
108 } |
|
109 vmStructsBase = addresses[0]; |
|
110 entityNameFieldOffset = addresses[1]; |
|
111 nameFieldOffset = addresses[2]; |
|
112 typeStringFieldOffset = addresses[3]; |
|
113 addressOffset = addresses[6]; |
|
114 entrySize = addresses[7]; |
|
115 nextElementAddress = vmStructsBase; |
|
116 nextElement = read(); |
|
117 } |
69 } |
118 |
70 |
119 @Override |
71 final long codeCacheHighBound = getFieldValue("CodeCache::_high_bound", Long.class); |
120 public boolean hasNext() { |
72 final long stubRoutineJintArrayCopy = getFieldValue("StubRoutines::_jint_arraycopy", Long.class); |
121 return nextElement != null; |
|
122 } |
|
123 |
|
124 @Override |
|
125 public VMFieldData next() { |
|
126 if (nextElement == null) { |
|
127 throw new NoSuchElementException("Next element is null"); |
|
128 } |
|
129 VMFieldData toReturn = nextElement; |
|
130 nextElementAddress += entrySize; |
|
131 nextElement = read(); |
|
132 return toReturn; |
|
133 } |
|
134 |
|
135 private VMFieldData read() { |
|
136 String entityFieldName = readCString( |
|
137 UNSAFE.getAddress(nextElementAddress + nameFieldOffset)); |
|
138 if (entityFieldName == null) { |
|
139 return null; |
|
140 } |
|
141 String fieldType = readCString(UNSAFE.getAddress( |
|
142 nextElementAddress + typeStringFieldOffset)); |
|
143 String entityName = readCString(UNSAFE.getAddress( |
|
144 nextElementAddress + entityNameFieldOffset)); |
|
145 Object value; |
|
146 if ("address".equals(fieldType)) { |
|
147 long address = UNSAFE.getAddress( |
|
148 nextElementAddress + addressOffset); |
|
149 value = address; |
|
150 } else { |
|
151 // non-address cases are not supported |
|
152 value = null; |
|
153 } |
|
154 return new VMFieldData(entityName, entityFieldName, fieldType, |
|
155 value); |
|
156 } |
|
157 |
|
158 private static String readCString(long address) { |
|
159 if (address == 0) { |
|
160 return null; |
|
161 } |
|
162 StringBuilder sb = new StringBuilder(); |
|
163 for (int i = 0;; i++) { |
|
164 char c = (char) UNSAFE.getByte(address + i); |
|
165 if (c == 0) { |
|
166 break; |
|
167 } |
|
168 sb.append(c); |
|
169 } |
|
170 return sb.toString(); |
|
171 } |
|
172 } |
|
173 |
|
174 private static class VMFieldData { |
|
175 public final String entityFieldName; |
|
176 public final String entityName; |
|
177 public final String fieldType; |
|
178 public final Object value; |
|
179 |
|
180 private VMFieldData(String entityName, String entityFieldName, |
|
181 String fieldType, Object value) { |
|
182 this.entityName = entityName; |
|
183 this.entityFieldName = entityFieldName; |
|
184 this.fieldType = fieldType; |
|
185 this.value = value; |
|
186 } |
|
187 } |
|
188 |
|
189 private static class TestCase { |
|
190 public final String entityName; |
|
191 public final String fieldType; |
|
192 public final String entityFieldName; |
|
193 public final Consumer consumer; |
|
194 private boolean found; |
|
195 |
|
196 public TestCase(String entityName, String entityFieldName, |
|
197 String fieldType, Consumer predicate) { |
|
198 Objects.requireNonNull(entityName, "Got null entityName"); |
|
199 Objects.requireNonNull(entityFieldName, "Got null entityFieldName"); |
|
200 Objects.requireNonNull(fieldType, "Got null type"); |
|
201 if (!"address".equals(fieldType)) { |
|
202 throw new Error("TESTBUG: unsupported testcase with fieldType=" |
|
203 + fieldType); |
|
204 } |
|
205 this.entityName = entityName; |
|
206 this.fieldType = fieldType; |
|
207 this.entityFieldName = entityFieldName; |
|
208 this.consumer = predicate; |
|
209 this.found = false; |
|
210 } |
|
211 |
|
212 public void check(VMFieldData data) { |
|
213 if (entityFieldName.equals(data.entityFieldName) |
|
214 && entityName.equals(data.entityName) |
|
215 && fieldType.equals(data.fieldType)) { |
|
216 Asserts.assertFalse(found, "Found 2 entries of " + this); |
|
217 found = true; |
|
218 consumer.accept(data.value); |
|
219 } |
|
220 } |
|
221 |
|
222 @Override |
|
223 public String toString() { |
|
224 return "CASE: entityName=" + entityName + " entityFieldName=" |
|
225 + entityFieldName + " fieldType=" + fieldType; |
|
226 } |
|
227 |
|
228 public boolean isFound() { |
|
229 return found; |
|
230 } |
|
231 } |
73 } |
232 } |
74 } |