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.arch != "aarch64" 28 * @library / /testlibrary 29 * @compile ../common/CompilerToVMHelper.java 30 * @build compiler.jvmci.compilerToVM.InitializeConfigurationTest 31 * @run main ClassFileInstaller 32 * jdk.vm.ci.hotspot.CompilerToVMHelper 33 * @run main/othervm -Xbootclasspath/a:. 34 * -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI 35 * compiler.jvmci.compilerToVM.InitializeConfigurationTest 36 */ 37 38 package compiler.jvmci.compilerToVM; 39 40 import java.util.ArrayList; 41 import java.util.Iterator; 42 import java.util.List; 43 import java.util.NoSuchElementException; 44 import java.util.Objects; 45 import java.util.function.Consumer; 46 import jdk.vm.ci.hotspot.CompilerToVMHelper; 47 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; 48 import jdk.test.lib.Asserts; 49 import jdk.test.lib.Utils; 50 import sun.misc.Unsafe; 51 52 public class InitializeConfigurationTest { 53 private static final Unsafe UNSAFE = Utils.getUnsafe(); 54 55 public static void main(String args[]) { 56 new InitializeConfigurationTest().runTest(generateTestCases()); 57 } 58 59 private static List<TestCase> generateTestCases() { 60 List<TestCase> result = new ArrayList<>(); 61 result.add(new TestCase("CodeCache", "_high_bound", "address", 62 InitializeConfigurationTest::verifyLongIsNotZero)); 63 result.add(new TestCase("StubRoutines", "_jint_arraycopy", "address", 64 InitializeConfigurationTest::verifyLongIsNotZero)); 65 return result; 66 } 67 68 private static void verifyLongIsNotZero(Object o) { 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 74 private void runTest(List<TestCase> tcases) { 75 VMStructDataReader reader = new VMStructDataReader( 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 } 118 119 @Override 120 public boolean hasNext() { 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 } 232 }