1 /* 2 * Copyright (c) 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 package jdk.vm.ci.hotspot; 24 25 import jdk.vm.ci.common.JVMCIError; 26 27 /** 28 * Access to VM configuration data. 29 */ 30 public class HotSpotVMConfigAccess { 31 32 /** 33 * Gets the available configuration data. 34 */ 35 public HotSpotVMConfigStore getStore() { 36 return store; 37 } 38 39 /** 40 * Gets the address of a C++ symbol. 41 * 42 * @param name name of C++ symbol 43 * @param notPresent if non-null and the symbol is not present then this value is returned 44 * @return the address of the symbol 45 * @throws JVMCIError if the symbol is not present and {@code notPresent == null} 46 */ 47 public long getAddress(String name, Long notPresent) { 48 Long entry = store.vmAddresses.get(name); 49 if (entry == null) { 50 if (notPresent != null) { 51 return notPresent; 52 } 53 throw new JVMCIError("expected VM symbol not found: " + name); 54 } 55 return entry; 56 } 57 58 /** 59 * Gets the address of a C++ symbol. 60 * 61 * @param name name of C++ symbol 62 * @return the address of the symbol 63 * @throws JVMCIError if the symbol is not present 64 */ 65 public long getAddress(String name) { 66 return getAddress(name, null); 67 } 68 69 /** 70 * Gets the value of a C++ constant. 71 * 72 * @param name name of the constant (e.g., {@code "frame::arg_reg_save_area_bytes"}) 73 * @param type the boxed type to which the constant value will be converted 74 * @param notPresent if non-null and the constant is not present then this value is returned 75 * @return the constant value converted to {@code type} 76 * @throws JVMCIError if the constant is not present and {@code notPresent == null} 77 */ 78 public <T> T getConstant(String name, Class<T> type, T notPresent) { 79 Long c = store.vmConstants.get(name); 80 if (c == null) { 81 if (notPresent != null) { 82 return notPresent; 83 } 84 throw new JVMCIError("expected VM constant not found: " + name); 85 } 86 return type.cast(convertValue(name, type, c, null)); 87 } 88 89 /** 90 * Gets the value of a C++ constant. 91 * 92 * @param name name of the constant (e.g., {@code "frame::arg_reg_save_area_bytes"}) 93 * @param type the boxed type to which the constant value will be converted 94 * @return the constant value converted to {@code type} 95 * @throws JVMCIError if the constant is not present 96 */ 97 public <T> T getConstant(String name, Class<T> type) { 98 return getConstant(name, type, null); 99 } 100 101 /** 102 * Gets the offset of a non-static C++ field. 103 * 104 * @param name fully qualified name of the field 105 * @param type the boxed type to which the offset value will be converted (must be 106 * {@link Integer} or {@link Long}) 107 * @param cppType if non-null, the expected C++ type of the field (e.g., {@code "HeapWord*"}) 108 * @param notPresent if non-null and the field is not present then this value is returned 109 * @return the offset in bytes of the requested field 110 * @throws JVMCIError if the field is static or not present and {@code notPresent} is null 111 */ 112 public <T> T getFieldOffset(String name, Class<T> type, String cppType, T notPresent) { 113 assert type == Integer.class || type == Long.class; 114 VMField entry = getField(name, cppType, notPresent == null); 115 if (entry == null) { 116 return notPresent; 117 } 118 if (entry.address != 0) { 119 throw new JVMCIError("cannot get offset of static field " + name); 120 } 121 return type.cast(convertValue(name, type, entry.offset, cppType)); 122 } 123 124 /** 125 * Gets the offset of a non-static C++ field. 126 * 127 * @param name fully qualified name of the field 128 * @param type the boxed type to which the offset value will be converted (must be 129 * {@link Integer} or {@link Long}) 130 * @param cppType if non-null, the expected C++ type of the field (e.g., {@code "HeapWord*"}) 131 * @return the offset in bytes of the requested field 132 * @throws JVMCIError if the field is static or not present 133 */ 134 public <T> T getFieldOffset(String name, Class<T> type, String cppType) { 135 return getFieldOffset(name, type, cppType, null); 136 } 137 138 /** 139 * Gets the offset of a non-static C++ field. 140 * 141 * @param name fully qualified name of the field 142 * @param type the boxed type to which the offset value will be converted (must be 143 * {@link Integer} or {@link Long}) 144 * @return the offset in bytes of the requested field 145 * @throws JVMCIError if the field is static or not present 146 */ 147 public <T> T getFieldOffset(String name, Class<T> type) { 148 return getFieldOffset(name, type, null, null); 149 } 150 151 /** 152 * Gets the address of a static C++ field. 153 * 154 * @param name fully qualified name of the field 155 * @param cppType if non-null, the expected C++ type of the field (e.g., {@code "HeapWord*"}) 156 * @param notPresent if non-null and the field is not present then this value is returned 157 * @return the address of the requested field 158 * @throws JVMCIError if the field is not static or not present and {@code notPresent} is null 159 */ 160 public long getFieldAddress(String name, String cppType, Long notPresent) { 161 VMField entry = getField(name, cppType, notPresent == null); 162 if (entry == null) { 163 return notPresent; 164 } 165 if (entry.address == 0) { 166 throw new JVMCIError(name + " is not a static field"); 167 } 168 return entry.address; 169 } 170 171 /** 172 * Gets the address of a static C++ field. 173 * 174 * @param name fully qualified name of the field 175 * @param cppType if non-null, the expected C++ type of the field (e.g., {@code "HeapWord*"}) 176 * @return the address of the requested field 177 * @throws JVMCIError if the field is not static or not present 178 */ 179 public long getFieldAddress(String name, String cppType) { 180 return getFieldAddress(name, cppType, null); 181 } 182 183 /** 184 * Gets the value of a static C++ field. 185 * 186 * @param name fully qualified name of the field 187 * @param type the boxed type to which the constant value will be converted 188 * @param cppType if non-null, the expected C++ type of the field (e.g., {@code "HeapWord*"}) 189 * @param notPresent if non-null and the field is not present then this value is returned 190 * @return the value of the requested field 191 * @throws JVMCIError if the field is not static or not present and {@code notPresent} is null 192 */ 193 public <T> T getFieldValue(String name, Class<T> type, String cppType, T notPresent) { 194 VMField entry = getField(name, cppType, notPresent == null); 195 if (entry == null) { 196 return notPresent; 197 } 198 if (entry.value == null) { 199 throw new JVMCIError(name + " is not a static field"); 200 } 201 return type.cast(convertValue(name, type, entry.value, cppType)); 202 } 203 204 /** 205 * Gets the value of a static C++ field. 206 * 207 * @param name fully qualified name of the field 208 * @param type the boxed type to which the constant value will be converted 209 * @param cppType if non-null, the expected C++ type of the field (e.g., {@code "HeapWord*"}) 210 * @return the value of the requested field 211 * @throws JVMCIError if the field is not static or not present 212 */ 213 public <T> T getFieldValue(String name, Class<T> type, String cppType) { 214 return getFieldValue(name, type, cppType, null); 215 } 216 217 /** 218 * Gets the value of a static C++ field. 219 * 220 * @param name fully qualified name of the field 221 * @param type the boxed type to which the constant value will be converted 222 * @return the value of the requested field 223 * @throws JVMCIError if the field is not static or not present 224 */ 225 public <T> T getFieldValue(String name, Class<T> type) { 226 return getFieldValue(name, type, null, null); 227 } 228 229 /** 230 * Gets a C++ field. 231 * 232 * @param name fully qualified name of the field 233 * @param cppType if non-null, the expected C++ type of the field (e.g., {@code "HeapWord*"}) 234 * @param required specifies if the field must be present 235 * @return the field 236 * @throws JVMCIError if the field is not present and {@code required == true} 237 */ 238 private VMField getField(String name, String cppType, boolean required) { 239 VMField entry = store.vmFields.get(name); 240 if (entry == null) { 241 if (!required) { 242 return null; 243 } 244 throw new JVMCIError("expected VM field not found: " + name); 245 } 246 247 // Make sure the native type is still the type we expect. 248 if (cppType != null && !cppType.equals(entry.type)) { 249 throw new JVMCIError("expected type " + cppType + " but VM field " + name + " is of type " + entry.type); 250 } 251 return entry; 252 } 253 254 /** 255 * Gets a VM flag value. 256 * 257 * @param name name of the flag (e.g., {@code "CompileTheWorldStartAt"}) 258 * @param type the boxed type to which the flag's value will be converted 259 * @return the flag's value converted to {@code type} or {@code notPresent} if the flag is not 260 * present 261 * @throws JVMCIError if the flag is not present 262 */ 263 public <T> T getFlag(String name, Class<T> type) { 264 return getFlag(name, type, null); 265 } 266 267 /** 268 * Gets a VM flag value. 269 * 270 * @param name name of the flag (e.g., {@code "CompileTheWorldStartAt"}) 271 * @param type the boxed type to which the flag's value will be converted 272 * @param notPresent if non-null and the flag is not present then this value is returned 273 * @return the flag's value converted to {@code type} or {@code notPresent} if the flag is not 274 * present 275 * @throws JVMCIError if the flag is not present and {@code notPresent == null} 276 */ 277 public <T> T getFlag(String name, Class<T> type, T notPresent) { 278 VMFlag entry = store.vmFlags.get(name); 279 Object value; 280 String cppType; 281 if (entry == null) { 282 // Fall back to VM call 283 value = store.compilerToVm.getFlagValue(name); 284 if (value == store.compilerToVm) { 285 if (notPresent != null) { 286 return notPresent; 287 } 288 throw new JVMCIError("expected VM flag not found: " + name); 289 } else { 290 cppType = null; 291 } 292 } else { 293 value = entry.value; 294 cppType = entry.type; 295 } 296 return type.cast(convertValue(name, type, value, cppType)); 297 } 298 299 private static <T> Object convertValue(String name, Class<T> toType, Object value, String cppType) throws JVMCIError { 300 if (toType == Boolean.class) { 301 if (value instanceof String) { 302 return Boolean.valueOf((String) value); 303 } else if (value instanceof Boolean) { 304 return value; 305 } else if (value instanceof Long) { 306 return ((long) value) != 0; 307 } 308 } else if (toType == Byte.class) { 309 if (value instanceof Long) { 310 return (byte) (long) value; 311 } 312 } else if (toType == Integer.class) { 313 if (value instanceof Integer) { 314 return value; 315 } else if (value instanceof Long) { 316 return (int) (long) value; 317 } 318 } else if (toType == String.class) { 319 if (value == null || value instanceof String) { 320 return value; 321 } 322 } else if (toType == Long.class) { 323 return value; 324 } 325 326 throw new JVMCIError("cannot convert " + name + " of type " + value.getClass().getSimpleName() + (cppType == null ? "" : " [" + cppType + "]") + " to " + toType.getSimpleName()); 327 } 328 329 private final HotSpotVMConfigStore store; 330 331 public HotSpotVMConfigAccess(HotSpotVMConfigStore store) { 332 this.store = store; 333 } 334 }