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