diff jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigAccess.java @ 23679:b5557b757040

fix HotSpotVMConfig startup performance (JDK-8159167)
author Doug Simon <doug.simon@oracle.com>
date Wed, 15 Jun 2016 00:00:41 +0200
parents
children 50465926fbeb
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigAccess.java	Wed Jun 15 00:00:41 2016 +0200
@@ -0,0 +1,332 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.common.JVMCIError;
+
+/**
+ * Access to VM configuration data.
+ */
+public class HotSpotVMConfigAccess {
+
+    /**
+     * Gets the address of a C++ symbol.
+     *
+     * @param name name of C++ symbol
+     * @param notPresent if non-null and the symbol is not present then this value is returned
+     * @return the address of the symbol
+     * @throws JVMCIError if the symbol is not present and {@code notPresent == null}
+     */
+    public long getAddress(String name, Long notPresent) {
+        Long entry = store.vmAddresses.get(name);
+        if (entry == null) {
+            if (notPresent != null) {
+                return notPresent;
+            }
+            throw new JVMCIError("expected VM symbol not found: " + name);
+        }
+        return entry;
+    }
+
+    /**
+     * Gets the address of a C++ symbol.
+     *
+     * @param name name of C++ symbol
+     * @return the address of the symbol
+     * @throws JVMCIError if the symbol is not present
+     */
+    public long getAddress(String name) {
+        return getAddress(name, null);
+    }
+
+    /**
+     * Gets the size of a C++ type.
+     *
+     * @param name name of the type
+     * @return the size in bytes of the requested field
+     * @throws JVMCIError if the field is not present and {@code notPresent} is null
+     */
+    public int getTypeSize(String name) {
+        Long entry = store.vmTypeSizes.get(name);
+        if (entry == null) {
+            throw new JVMCIError("expected VM type not found: " + name);
+        }
+        return (int) (long) entry;
+    }
+
+    /**
+     * Gets the value of a C++ constant.
+     *
+     * @param name name of the constant (e.g., {@code "frame::arg_reg_save_area_bytes"})
+     * @param type the boxed type to which the constant value will be converted
+     * @param notPresent if non-null and the constant is not present then this value is returned
+     * @return the constant value converted to {@code type}
+     * @throws JVMCIError if the constant is not present and {@code notPresent == null}
+     */
+    public <T> T getConstant(String name, Class<T> type, T notPresent) {
+        Long c = store.vmConstants.get(name);
+        if (c == null) {
+            if (notPresent != null) {
+                return notPresent;
+            }
+            throw new JVMCIError("expected VM constant not found: " + name);
+        }
+        return type.cast(convertValue(name, type, c, null));
+    }
+
+    /**
+     * Gets the value of a C++ constant.
+     *
+     * @param name name of the constant (e.g., {@code "frame::arg_reg_save_area_bytes"})
+     * @param type the boxed type to which the constant value will be converted
+     * @return the constant value converted to {@code type}
+     * @throws JVMCIError if the constant is not present
+     */
+    public <T> T getConstant(String name, Class<T> type) {
+        return getConstant(name, type, null);
+    }
+
+    /**
+     * Gets the offset of a non-static C++ field.
+     *
+     * @param name fully qualified name of the field
+     * @param type the boxed type to which the offset value will be converted (must be
+     *            {@link Integer} or {@link Long})
+     * @param cppType if non-null, the expected C++ type of the field (e.g., {@code "HeapWord*"})
+     * @param notPresent if non-null and the field is not present then this value is returned
+     * @return the offset in bytes of the requested field
+     * @throws JVMCIError if the field is static or not present and {@code notPresent} is null
+     */
+    public <T> T getFieldOffset(String name, Class<T> type, String cppType, T notPresent) {
+        assert type == Integer.class || type == Long.class;
+        VMField entry = getField(name, cppType, notPresent == null);
+        if (entry == null) {
+            return notPresent;
+        }
+        if (entry.address != 0) {
+            throw new JVMCIError("cannot get offset of static field " + name);
+        }
+        return entry == null ? notPresent : type.cast(convertValue(name, type, entry.offset, cppType));
+    }
+
+    /**
+     * Gets the offset of a non-static C++ field.
+     *
+     * @param name fully qualified name of the field
+     * @param type the boxed type to which the offset value will be converted (must be
+     *            {@link Integer} or {@link Long})
+     * @param cppType if non-null, the expected C++ type of the field (e.g., {@code "HeapWord*"})
+     * @return the offset in bytes of the requested field
+     * @throws JVMCIError if the field is static or not present
+     */
+    public <T> T getFieldOffset(String name, Class<T> type, String cppType) {
+        return getFieldOffset(name, type, cppType, null);
+    }
+
+    /**
+     * Gets the offset of a non-static C++ field.
+     *
+     * @param name fully qualified name of the field
+     * @param type the boxed type to which the offset value will be converted (must be
+     *            {@link Integer} or {@link Long})
+     * @return the offset in bytes of the requested field
+     * @throws JVMCIError if the field is static or not present
+     */
+    public <T> T getFieldOffset(String name, Class<T> type) {
+        return getFieldOffset(name, type, null, null);
+    }
+
+    /**
+     * Gets the address of a static C++ field.
+     *
+     * @param name fully qualified name of the field
+     * @param cppType if non-null, the expected C++ type of the field (e.g., {@code "HeapWord*"})
+     * @param notPresent if non-null and the field is not present then this value is returned
+     * @return the address of the requested field
+     * @throws JVMCIError if the field is not static or not present and {@code notPresent} is null
+     */
+    public long getFieldAddress(String name, String cppType, Long notPresent) {
+        VMField entry = getField(name, cppType, notPresent == null);
+        if (entry == null) {
+            return notPresent;
+        }
+        if (entry.address == 0) {
+            throw new JVMCIError(name + " is not a static field");
+        }
+        return entry == null ? notPresent : entry.address;
+    }
+
+    /**
+     * Gets the address of a static C++ field.
+     *
+     * @param name fully qualified name of the field
+     * @param cppType if non-null, the expected C++ type of the field (e.g., {@code "HeapWord*"})
+     * @return the address of the requested field
+     * @throws JVMCIError if the field is not static or not present
+     */
+    public long getFieldAddress(String name, String cppType) {
+        return getFieldAddress(name, cppType, null);
+    }
+
+    /**
+     * Gets the value of a static C++ field.
+     *
+     * @param name fully qualified name of the field
+     * @param type the boxed type to which the constant value will be converted
+     * @param cppType if non-null, the expected C++ type of the field (e.g., {@code "HeapWord*"})
+     * @param notPresent if non-null and the field is not present then this value is returned
+     * @return the value of the requested field
+     * @throws JVMCIError if the field is not static or not present and {@code notPresent} is null
+     */
+    public <T> T getFieldValue(String name, Class<T> type, String cppType, T notPresent) {
+        VMField entry = getField(name, cppType, notPresent == null);
+        if (entry == null) {
+            return notPresent;
+        }
+        if (entry.value == null) {
+            throw new JVMCIError(name + " is not a static field");
+        }
+        return type.cast(convertValue(name, type, entry.value, cppType));
+    }
+
+    /**
+     * Gets the value of a static C++ field.
+     *
+     * @param name fully qualified name of the field
+     * @param type the boxed type to which the constant value will be converted
+     * @param cppType if non-null, the expected C++ type of the field (e.g., {@code "HeapWord*"})
+     * @return the value of the requested field
+     * @throws JVMCIError if the field is not static or not present
+     */
+    public <T> T getFieldValue(String name, Class<T> type, String cppType) {
+        return getFieldValue(name, type, cppType, null);
+    }
+
+    /**
+     * Gets the value of a static C++ field.
+     *
+     * @param name fully qualified name of the field
+     * @param type the boxed type to which the constant value will be converted
+     * @return the value of the requested field
+     * @throws JVMCIError if the field is not static or not present
+     */
+    public <T> T getFieldValue(String name, Class<T> type) {
+        return getFieldValue(name, type, null, null);
+    }
+
+    /**
+     * Gets a C++ field.
+     *
+     * @param name fully qualified name of the field
+     * @param cppType if non-null, the expected C++ type of the field (e.g., {@code "HeapWord*"})
+     * @param required specifies if the field must be present
+     * @return the field
+     * @throws JVMCIError if the field is not present and {@code required == true}
+     */
+    private VMField getField(String name, String cppType, boolean required) {
+        VMField entry = store.vmFields.get(name);
+        if (entry == null) {
+            if (!required) {
+                return null;
+            }
+            throw new JVMCIError("expected VM field not found: " + name);
+        }
+
+        // Make sure the native type is still the type we expect.
+        if (cppType != null && !cppType.equals(entry.type)) {
+            throw new JVMCIError("expected type " + cppType + " but VM field " + name + " is of type " + entry.type);
+        }
+        return entry;
+    }
+
+    /**
+     * Gets a VM flag value.
+     *
+     * @param name name of the flag (e.g., {@code "CompileTheWorldStartAt"})
+     * @param type the boxed type to which the flag's value will be converted
+     * @return the flag's value converted to {@code type} or {@code notPresent} if the flag is not
+     *         present
+     * @throws JVMCIError if the flag is not present
+     */
+    public <T> T getFlag(String name, Class<T> type) {
+        return getFlag(name, type, null);
+    }
+
+    /**
+     * Gets a VM flag value.
+     *
+     * @param name name of the flag (e.g., {@code "CompileTheWorldStartAt"})
+     * @param type the boxed type to which the flag's value will be converted
+     * @param notPresent if non-null and the flag is not present then this value is returned
+     * @return the flag's value converted to {@code type} or {@code notPresent} if the flag is not
+     *         present
+     * @throws JVMCIError if the flag is not present and {@code notPresent == null}
+     */
+    public <T> T getFlag(String name, Class<T> type, T notPresent) {
+        VMFlag entry = store.vmFlags.get(name);
+        if (entry == null) {
+            if (notPresent != null) {
+                return notPresent;
+            }
+            throw new JVMCIError("expected VM flag not found: " + name);
+        }
+        return type.cast(convertValue(name, type, entry.value, entry.type));
+    }
+
+    private static <T> Object convertValue(String name, Class<T> toType, Object value, String cppType) throws JVMCIError {
+        if (toType == Boolean.class) {
+            if (value instanceof String) {
+                return Boolean.valueOf((String) value);
+            } else if (value instanceof Boolean) {
+                return value;
+            } else if (value instanceof Long) {
+                return ((long) value) != 0;
+            }
+        } else if (toType == Byte.class) {
+            if (value instanceof Long) {
+                return (byte) (long) value;
+            }
+        } else if (toType == Integer.class) {
+            if (value instanceof Integer) {
+                return value;
+            } else if (value instanceof Long) {
+                return (int) (long) value;
+            }
+        } else if (toType == Long.class) {
+            return (long) value;
+        }
+
+        throw new JVMCIError("cannot convert " + name + " of type " + value.getClass().getSimpleName() + (cppType == null ? "" : " [" + cppType + "]") + " to " + toType.getSimpleName());
+    }
+
+    private final HotSpotVMConfigStore store;
+
+    public HotSpotVMConfigAccess(HotSpotVMConfigStore store) {
+        this.store = store;
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName();
+    }
+}