Mercurial > hg > graal-jvmci-8
changeset 22422:a98a02bad801
Add simple interface to control caching policy for ResolvedJavaTypes
line wrap: on
line diff
--- a/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotJVMCIRuntime.java Thu Aug 13 11:10:21 2015 -0700 +++ b/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotJVMCIRuntime.java Thu Aug 13 11:53:13 2015 -0700 @@ -154,22 +154,7 @@ protected final HotSpotVMConfig config; private final JVMCIBackend hostBackend; - /** - * JVMCI mirrors are stored as a {@link ClassValue} associated with the {@link Class} of the - * type. This data structure stores both {@link HotSpotResolvedObjectType} and - * {@link HotSpotResolvedPrimitiveType} types. - */ - private final ClassValue<ResolvedJavaType> jvmciMirrors = new ClassValue<ResolvedJavaType>() { - @Override - protected ResolvedJavaType computeValue(Class<?> javaClass) { - if (javaClass.isPrimitive()) { - Kind kind = Kind.fromJavaClass(javaClass); - return new HotSpotResolvedPrimitiveType(kind); - } else { - return new HotSpotResolvedObjectTypeImpl(javaClass); - } - } - }; + protected final JVMCIMetaAccessContext metaAccessContext; private final Map<Class<? extends Architecture>, JVMCIBackend> backends = new HashMap<>(); @@ -198,6 +183,27 @@ }); } vmEventListeners = listeners; + + JVMCIMetaAccessContext context = null; + for (HotSpotVMEventListener vmEventListener : vmEventListeners) { + context = vmEventListener.createMetaAccessContext(this, HotSpotJVMCIRuntime::createClass); + if (context != null) { + break; + } + } + if (context == null) { + context = new JVMCIGlobalMetaAccessContext(HotSpotJVMCIRuntime::createClass); + } + metaAccessContext = context; + } + + private static ResolvedJavaType createClass(Class<?> javaClass) { + if (javaClass.isPrimitive()) { + Kind kind = Kind.fromJavaClass(javaClass); + return new HotSpotResolvedPrimitiveType(kind); + } else { + return new HotSpotResolvedObjectTypeImpl(javaClass); + } } private JVMCIBackend registerBackend(JVMCIBackend backend) { @@ -208,7 +214,7 @@ } public ResolvedJavaType fromClass(Class<?> javaClass) { - return jvmciMirrors.get(javaClass); + return metaAccessContext.fromClass(javaClass); } public HotSpotVMConfig getConfig() { @@ -219,6 +225,10 @@ return compilerToVm; } + public JVMCIMetaAccessContext getMetaAccessContext() { + return metaAccessContext; + } + public JavaType lookupType(String name, HotSpotResolvedObjectType accessingType, boolean resolve) { Objects.requireNonNull(accessingType, "cannot resolve type without an accessing class"); // If the name represents a primitive type we can short-circuit the lookup.
--- a/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotJVMCIRuntimeProvider.java Thu Aug 13 11:10:21 2015 -0700 +++ b/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotJVMCIRuntimeProvider.java Thu Aug 13 11:53:13 2015 -0700 @@ -60,6 +60,8 @@ */ ResolvedJavaType fromClass(Class<?> clazz); + JVMCIMetaAccessContext getMetaAccessContext(); + /** * The offset from the origin of an array to the first element. *
--- a/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotMetaAccessProvider.java Thu Aug 13 11:10:21 2015 -0700 +++ b/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotMetaAccessProvider.java Thu Aug 13 11:53:13 2015 -0700 @@ -23,7 +23,6 @@ package jdk.internal.jvmci.hotspot; import static jdk.internal.jvmci.common.UnsafeAccess.*; -import static jdk.internal.jvmci.hotspot.HotSpotResolvedJavaType.*; import static jdk.internal.jvmci.hotspot.HotSpotResolvedObjectTypeImpl.*; import java.lang.reflect.*; @@ -105,7 +104,7 @@ final long offset = Modifier.isStatic(modifiers) ? unsafe.staticFieldOffset(reflectionField) : unsafe.objectFieldOffset(reflectionField); HotSpotResolvedObjectType holder = fromObjectClass(fieldHolder); - JavaType type = fromClass(fieldType); + JavaType type = runtime.fromClass(fieldType); if (offset != -1) { HotSpotResolvedObjectType resolved = holder;
--- a/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotMethodHandleAccessProvider.java Thu Aug 13 11:10:21 2015 -0700 +++ b/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotMethodHandleAccessProvider.java Thu Aug 13 11:53:13 2015 -0700 @@ -23,7 +23,6 @@ package jdk.internal.jvmci.hotspot; import static jdk.internal.jvmci.hotspot.HotSpotJVMCIRuntime.*; -import static jdk.internal.jvmci.hotspot.HotSpotResolvedJavaType.*; import static jdk.internal.jvmci.hotspot.HotSpotResolvedObjectTypeImpl.*; import jdk.internal.jvmci.common.*; import jdk.internal.jvmci.meta.*; @@ -56,7 +55,7 @@ */ private static ResolvedJavaField findFieldInClass(String className, String fieldName) throws ClassNotFoundException { Class<?> clazz = Class.forName(className); - ResolvedJavaType type = fromClass(clazz); + ResolvedJavaType type = runtime().fromClass(clazz); ResolvedJavaField[] fields = type.getInstanceFields(false); for (ResolvedJavaField field : fields) { if (field.getName().equals(fieldName)) {
--- a/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotResolvedJavaType.java Thu Aug 13 11:10:21 2015 -0700 +++ b/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotResolvedJavaType.java Thu Aug 13 11:53:13 2015 -0700 @@ -22,20 +22,10 @@ */ package jdk.internal.jvmci.hotspot; -import static jdk.internal.jvmci.hotspot.HotSpotJVMCIRuntime.*; import jdk.internal.jvmci.meta.*; public abstract class HotSpotResolvedJavaType extends HotSpotJavaType implements ResolvedJavaType { - /** - * Gets the JVMCI mirror for a {@link Class} object. - * - * @return the {@link HotSpotResolvedJavaType} corresponding to {@code javaClass} - */ - public static ResolvedJavaType fromClass(Class<?> javaClass) { - return runtime().fromClass(javaClass); - } - public HotSpotResolvedJavaType(String name) { super(name); }
--- a/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotResolvedObjectTypeImpl.java Thu Aug 13 11:10:21 2015 -0700 +++ b/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotResolvedObjectTypeImpl.java Thu Aug 13 11:53:13 2015 -0700 @@ -137,7 +137,7 @@ @Override public ResolvedJavaType getComponentType() { Class<?> javaComponentType = mirror().getComponentType(); - return javaComponentType == null ? null : fromClass(javaComponentType); + return javaComponentType == null ? null : runtime().fromClass(javaComponentType); } @Override
--- a/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotResolvedPrimitiveType.java Thu Aug 13 11:10:21 2015 -0700 +++ b/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotResolvedPrimitiveType.java Thu Aug 13 11:53:13 2015 -0700 @@ -29,8 +29,8 @@ import java.net.*; import jdk.internal.jvmci.common.*; +import jdk.internal.jvmci.meta.Assumptions.AssumptionResult; import jdk.internal.jvmci.meta.*; -import jdk.internal.jvmci.meta.Assumptions.*; /** * Implementation of {@link JavaType} for primitive HotSpot types. @@ -44,7 +44,7 @@ * * <p> * <b>NOTE</b>: Creating an instance of this class does not install the mirror for the - * {@link Class} type. Use {@link #fromClass(Class)} instead. + * {@link Class} type. Use {@link HotSpotJVMCIRuntimeProvider#fromClass(Class)} instead. * </p> * * @param kind the Kind to create the mirror for
--- a/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotVMEventListener.java Thu Aug 13 11:10:21 2015 -0700 +++ b/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotVMEventListener.java Thu Aug 13 11:53:13 2015 -0700 @@ -22,7 +22,10 @@ */ package jdk.internal.jvmci.hotspot; +import java.util.function.*; + import jdk.internal.jvmci.code.*; +import jdk.internal.jvmci.meta.*; public interface HotSpotVMEventListener { @@ -63,9 +66,26 @@ } /** + * Perform any extra initialization required. + * * @param hotSpotJVMCIRuntime + * @param compilerToVM the current {@link CompilerToVM instance} + * @return the original compilerToVM instance or a proxied version. */ default CompilerToVM completeInitialization(HotSpotJVMCIRuntime hotSpotJVMCIRuntime, CompilerToVM compilerToVM) { return compilerToVM; } + + /** + * Create a custom {@link JVMCIMetaAccessContext} to be used for managing the lifetime of loaded + * metadata. It a custom one isn't created then the default implementation will be a single + * context with globally shared instances of {@link ResolvedJavaType} that are never released. + * + * @param hotSpotJVMCIRuntime + * @param factory the factory function to create new ResolvedJavaTypes + * @return a custom context or null + */ + default JVMCIMetaAccessContext createMetaAccessContext(HotSpotJVMCIRuntime hotSpotJVMCIRuntime, Function<Class<?>, ResolvedJavaType> factory) { + return null; + } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jvmci/jdk.internal.jvmci.meta/src/jdk/internal/jvmci/meta/JVMCIGlobalMetaAccessContext.java Thu Aug 13 11:53:13 2015 -0700 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015, 2015, 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.internal.jvmci.meta; + +import java.util.function.*; + +/** + * Caches the {@link ResolvedJavaType} for a class in a {@link ClassValue}. The instances live + * forever with no way to clean them up once they are no longer in use. + */ + +public class JVMCIGlobalMetaAccessContext implements JVMCIMetaAccessContext { + + /** + * JVMCI mirrors are stored as a {@link ClassValue} associated with the {@link Class} of the + * type. + */ + protected final ClassValue<ResolvedJavaType> jvmciMirrors = new ClassValue<ResolvedJavaType>() { + @Override + protected ResolvedJavaType computeValue(Class<?> javaClass) { + return factory.apply(javaClass); + } + + }; + protected final Function<Class<?>, ResolvedJavaType> factory; + + public JVMCIGlobalMetaAccessContext(Function<Class<?>, ResolvedJavaType> factory) { + this.factory = factory; + } + + public ResolvedJavaType fromClass(Class<?> javaClass) { + return jvmciMirrors.get(javaClass); + } + + public boolean flush() { + // There is no mechanism to flush all data. + return false; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jvmci/jdk.internal.jvmci.meta/src/jdk/internal/jvmci/meta/JVMCIMetaAccessContext.java Thu Aug 13 11:53:13 2015 -0700 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2015, 2015, 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.internal.jvmci.meta; + +/** + * A context in which the results looking up the {@link ResolvedJavaType} for a {@link Class} are + * cached. + */ +public interface JVMCIMetaAccessContext { + + /** + * Gets the JVMCI mirror for a {@link Class} object. + * + * @return the {@link ResolvedJavaType} corresponding to {@code javaClass} + */ + + ResolvedJavaType fromClass(Class<?> clazz); + + /** + * An optional operation which drops all currently cached information. + * + * @return true if any work was performed + */ + boolean flush(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jvmci/jdk.internal.jvmci.meta/src/jdk/internal/jvmci/meta/JVMCIThreadLocalMetaAccessContext.java Thu Aug 13 11:53:13 2015 -0700 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2015, 2015, 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.internal.jvmci.meta; + +import java.util.*; +import java.util.function.*; + +/** + * A per thread cache of {@link ResolvedJavaType}s. The per thread cache can be flushed by using + * {@link #flush()} but there is no way to globally flush all caches. + */ +public class JVMCIThreadLocalMetaAccessContext implements JVMCIMetaAccessContext { + + protected final ThreadLocal<Map<Class<?>, ResolvedJavaType>> threadLocalMap = new ThreadLocal<Map<Class<?>, ResolvedJavaType>>() { + @Override + protected Map<Class<?>, ResolvedJavaType> initialValue() { + return new HashMap<>(); + } + }; + + protected final Function<Class<?>, ResolvedJavaType> factory; + + public JVMCIThreadLocalMetaAccessContext(Function<Class<?>, ResolvedJavaType> factory) { + this.factory = factory; + } + + public ResolvedJavaType fromClass(Class<?> javaClass) { + Map<Class<?>, ResolvedJavaType> map = threadLocalMap.get(); + ResolvedJavaType type = map.get(javaClass); + if (type == null) { + type = factory.apply(javaClass); + map.put(javaClass, type); + } + return type; + } + + /** + * Drop all current cached state. + */ + public boolean flush() { + threadLocalMap.remove(); + return true; + } +}