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