changeset 22422:a98a02bad801

Add simple interface to control caching policy for ResolvedJavaTypes
author Tom Rodriguez <tom.rodriguez@oracle.com>
date Thu, 13 Aug 2015 11:53:13 -0700
parents 2b9729c833ab
children 4a532b03e2cd
files jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotJVMCIRuntime.java jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotJVMCIRuntimeProvider.java jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotMetaAccessProvider.java jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotMethodHandleAccessProvider.java jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotResolvedJavaType.java jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotResolvedObjectTypeImpl.java jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotResolvedPrimitiveType.java jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotVMEventListener.java jvmci/jdk.internal.jvmci.meta/src/jdk/internal/jvmci/meta/JVMCIGlobalMetaAccessContext.java jvmci/jdk.internal.jvmci.meta/src/jdk/internal/jvmci/meta/JVMCIMetaAccessContext.java jvmci/jdk.internal.jvmci.meta/src/jdk/internal/jvmci/meta/JVMCIThreadLocalMetaAccessContext.java
diffstat 11 files changed, 222 insertions(+), 34 deletions(-) [+]
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;
+    }
+}