changeset 56732:81ad1da857f6

8232904: Update JVMCI Reviewed-by: dnsimon
author kvn
date Thu, 24 Oct 2019 16:58:39 -0700
parents 5a9dba5a3eeb
children d428456b5830
files src/hotspot/share/jvmci/jvmciCompilerToVM.cpp src/hotspot/share/jvmci/vmStructs_jvmci.cpp src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaType.java src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSpeculationEncoding.java src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/SharedHotSpotSpeculationLog.java src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/EncodedSpeculationReason.java test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestHotSpotSpeculationLog.java
diffstat 12 files changed, 232 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp	Thu Oct 24 12:18:32 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp	Thu Oct 24 16:58:39 2019 -0700
@@ -2330,6 +2330,16 @@
   return true;
 C2V_END
 
+C2V_VMENTRY_PREFIX(jlong, getCurrentJavaThread, (JNIEnv* env, jobject c2vm))
+  if (base_thread == NULL) {
+    // Called from unattached JVMCI shared library thread
+    return 0L;
+  }
+  JVMCITraceMark jtm("getCurrentJavaThread");
+  assert(base_thread->is_Java_thread(), "just checking");
+  return (jlong) p2i(base_thread);
+C2V_END
+
 C2V_VMENTRY_PREFIX(jboolean, attachCurrentThread, (JNIEnv* env, jobject c2vm, jboolean as_daemon))
   if (base_thread == NULL) {
     // Called from unattached JVMCI shared library thread
@@ -2743,6 +2753,7 @@
   {CC "deleteGlobalHandle",                           CC "(J)V",                                                                            FN_PTR(deleteGlobalHandle)},
   {CC "registerNativeMethods",                        CC "(" CLASS ")[J",                                                                   FN_PTR(registerNativeMethods)},
   {CC "isCurrentThreadAttached",                      CC "()Z",                                                                             FN_PTR(isCurrentThreadAttached)},
+  {CC "getCurrentJavaThread",                         CC "()J",                                                                             FN_PTR(getCurrentJavaThread)},
   {CC "attachCurrentThread",                          CC "(Z)Z",                                                                            FN_PTR(attachCurrentThread)},
   {CC "detachCurrentThread",                          CC "()V",                                                                             FN_PTR(detachCurrentThread)},
   {CC "translate",                                    CC "(" OBJECT ")J",                                                                   FN_PTR(translate)},
--- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp	Thu Oct 24 12:18:32 2019 -0700
+++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp	Thu Oct 24 16:58:39 2019 -0700
@@ -180,6 +180,7 @@
   nonstatic_field(JavaThread,                  _pending_transfer_to_interpreter,              bool)                                  \
   nonstatic_field(JavaThread,                  _jvmci_counters,                               jlong*)                                \
   nonstatic_field(JavaThread,                  _should_post_on_exceptions_flag,               int)                                   \
+  nonstatic_field(JavaThread,                  _jni_environment,                              JNIEnv)                                \
   nonstatic_field(JavaThread,                  _reserved_stack_activation,                    address)                               \
                                                                                                                                      \
   static_field(java_lang_Class,                _klass_offset,                                 int)                                   \
@@ -538,6 +539,7 @@
   declare_constant(FieldInfo::field_slots)                                \
                                                                           \
   declare_constant(InstanceKlass::linked)                                 \
+  declare_constant(InstanceKlass::being_initialized)                      \
   declare_constant(InstanceKlass::fully_initialized)                      \
   declare_constant(InstanceKlass::_misc_is_unsafe_anonymous)              \
                                                                           \
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java	Thu Oct 24 12:18:32 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java	Thu Oct 24 16:58:39 2019 -0700
@@ -967,6 +967,11 @@
     native boolean isCurrentThreadAttached();
 
     /**
+     * @see HotSpotJVMCIRuntime#getCurrentJavaThread()
+     */
+    native long getCurrentJavaThread();
+
+    /**
      * @see HotSpotJVMCIRuntime#attachCurrentThread
      */
     native boolean attachCurrentThread(boolean asDaemon);
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java	Thu Oct 24 12:18:32 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java	Thu Oct 24 16:58:39 2019 -0700
@@ -999,6 +999,14 @@
     }
 
     /**
+     * Gets the address of the HotSpot {@code JavaThread} C++ object for the current thread. This
+     * will return {@code 0} if called from an unattached JVMCI shared library thread.
+     */
+    public long getCurrentJavaThread() {
+        return compilerToVm.getCurrentJavaThread();
+    }
+
+    /**
      * Ensures the current thread is attached to the peer runtime.
      *
      * @param asDaemon if the thread is not yet attached, should it be attached as a daemon
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaType.java	Thu Oct 24 12:18:32 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaType.java	Thu Oct 24 16:58:39 2019 -0700
@@ -52,4 +52,13 @@
         }
         return arrayOfType;
     }
+
+    /**
+     * Checks whether this type is currently being initialized. If a type is being initialized it
+     * implies that it was {@link #isLinked() linked} and that the static initializer is currently
+     * being run.
+     *
+     * @return {@code true} if this type is being initialized
+     */
+    abstract boolean isBeingInitialized();
 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java	Thu Oct 24 12:18:32 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java	Thu Oct 24 16:58:39 2019 -0700
@@ -360,6 +360,11 @@
     }
 
     @Override
+    public boolean isBeingInitialized() {
+        return isArray() ? false : getInitState() == config().instanceKlassStateBeingInitialized;
+    }
+
+    @Override
     public boolean isLinked() {
         return isArray() ? true : getInitState() >= config().instanceKlassStateLinked;
     }
@@ -379,7 +384,7 @@
     public void initialize() {
         if (!isInitialized()) {
             runtime().compilerToVm.ensureInitialized(this);
-            assert isInitialized();
+            assert isInitialized() || isBeingInitialized();
         }
     }
 
@@ -578,11 +583,6 @@
             return new AssumptionResult<>(resolvedMethod);
         }
 
-        if (resolvedMethod.canBeStaticallyBound()) {
-            // No assumptions are required.
-            return new AssumptionResult<>(resolvedMethod);
-        }
-
         ResolvedJavaMethod result = resolvedMethod.uniqueConcreteMethod(this);
         if (result != null) {
             return new AssumptionResult<>(result, new ConcreteMethod(method, this, result));
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java	Thu Oct 24 12:18:32 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java	Thu Oct 24 16:58:39 2019 -0700
@@ -150,6 +150,11 @@
     }
 
     @Override
+    public boolean isBeingInitialized() {
+        return false;
+    }
+
+    @Override
     public boolean isLinked() {
         return true;
     }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSpeculationEncoding.java	Thu Oct 24 12:18:32 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSpeculationEncoding.java	Thu Oct 24 16:58:39 2019 -0700
@@ -29,7 +29,6 @@
 import java.security.NoSuchAlgorithmException;
 import java.util.Arrays;
 
-import jdk.vm.ci.common.JVMCIError;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 import jdk.vm.ci.meta.ResolvedJavaType;
 import jdk.vm.ci.meta.SpeculationLog.SpeculationReasonEncoding;
@@ -37,8 +36,8 @@
 /**
  * Implements a {@link SpeculationReasonEncoding} that {@linkplain #getByteArray() produces} a byte
  * array. Data is added via a {@link DataOutputStream}. When producing the final byte array, if the
- * total length of data exceeds the length of a SHA-1 digest, then a SHA-1 digest of the data is
- * produced instead.
+ * total length of data exceeds the length of a SHA-1 digest and a SHA-1 digest algorithm is
+ * available, then a SHA-1 digest of the data is produced instead.
  */
 final class HotSpotSpeculationEncoding extends ByteArrayOutputStream implements SpeculationReasonEncoding {
 
@@ -152,21 +151,33 @@
     }
 
     /**
-     * Prototype SHA1 digest that is cloned before use.
+     * Prototype SHA1 digest.
      */
-    private static final MessageDigest SHA1 = getSHA1();
-    private static final int SHA1_LENGTH = SHA1.getDigestLength();
+    private static final MessageDigest SHA1;
 
-    private static MessageDigest getSHA1() {
+    /**
+     * Cloning the prototype is quicker than calling {@link MessageDigest#getInstance(String)} every
+     * time.
+     */
+    private static final boolean SHA1_IS_CLONEABLE;
+    private static final int SHA1_LENGTH;
+
+    static {
+        MessageDigest sha1 = null;
+        boolean sha1IsCloneable = false;
         try {
-            MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
+            sha1 = MessageDigest.getInstance("SHA-1");
             sha1.clone();
-            return sha1;
-        } catch (CloneNotSupportedException | NoSuchAlgorithmException e) {
+            sha1IsCloneable = true;
+        } catch (NoSuchAlgorithmException e) {
             // Should never happen given that SHA-1 is mandated in a
-            // compliant Java platform implementation.
-            throw new JVMCIError("Expect a cloneable implementation of a SHA-1 message digest to be available", e);
+            // compliant Java platform implementation. However, be
+            // conservative and fall back to not using a digest.
+        } catch (CloneNotSupportedException e) {
         }
+        SHA1 = sha1;
+        SHA1_IS_CLONEABLE = sha1IsCloneable;
+        SHA1_LENGTH = SHA1 == null ? 20 : SHA1.getDigestLength();
     }
 
     /**
@@ -175,12 +186,12 @@
      */
     byte[] getByteArray() {
         if (result == null) {
-            if (count > SHA1_LENGTH) {
+            if (SHA1 != null && count > SHA1_LENGTH) {
                 try {
-                    MessageDigest md = (MessageDigest) SHA1.clone();
+                    MessageDigest md = SHA1_IS_CLONEABLE ? (MessageDigest) SHA1.clone() : MessageDigest.getInstance("SHA-1");
                     md.update(buf, 0, count);
                     result = md.digest();
-                } catch (CloneNotSupportedException e) {
+                } catch (CloneNotSupportedException | NoSuchAlgorithmException e) {
                     throw new InternalError(e);
                 }
             } else {
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java	Thu Oct 24 12:18:32 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java	Thu Oct 24 16:58:39 2019 -0700
@@ -107,6 +107,7 @@
 
     final int instanceKlassStateLinked = getConstant("InstanceKlass::linked", Integer.class);
     final int instanceKlassStateFullyInitialized = getConstant("InstanceKlass::fully_initialized", Integer.class);
+    final int instanceKlassStateBeingInitialized = getConstant("InstanceKlass::being_initialized", Integer.class);
     final int instanceKlassMiscIsUnsafeAnonymous = getConstant("InstanceKlass::_misc_is_unsafe_anonymous", Integer.class);
 
     final int annotationsFieldAnnotationsOffset = getFieldOffset("Annotations::_fields_annotations", Integer.class, "Array<AnnotationArray*>*");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/SharedHotSpotSpeculationLog.java	Thu Oct 24 16:58:39 2019 -0700
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014, 2019, 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;
+
+/**
+ * A wrapper that holds a strong reference to a "master" speculation log that
+ * {@linkplain HotSpotSpeculationLog#managesFailedSpeculations() manages} the failed speculations
+ * list.
+ */
+public class SharedHotSpotSpeculationLog extends HotSpotSpeculationLog {
+    private final HotSpotSpeculationLog masterLog;
+
+    public SharedHotSpotSpeculationLog(HotSpotSpeculationLog masterLog) {
+        super(masterLog.getFailedSpeculationsAddress());
+        this.masterLog = masterLog;
+    }
+
+    @Override
+    public String toString() {
+        return masterLog.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/EncodedSpeculationReason.java	Thu Oct 24 16:58:39 2019 -0700
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2019, 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.meta;
+
+import java.util.Arrays;
+import java.util.function.Supplier;
+
+import jdk.vm.ci.meta.SpeculationLog.SpeculationReason;
+
+/**
+ * An implementation of {@link SpeculationReason} based on encoded values.
+ */
+public class EncodedSpeculationReason implements SpeculationReason {
+    final int groupId;
+    final String groupName;
+    final Object[] context;
+    private SpeculationLog.SpeculationReasonEncoding encoding;
+
+    public EncodedSpeculationReason(int groupId, String groupName, Object[] context) {
+        this.groupId = groupId;
+        this.groupName = groupName;
+        this.context = context;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof EncodedSpeculationReason) {
+            if (obj instanceof EncodedSpeculationReason) {
+                EncodedSpeculationReason that = (EncodedSpeculationReason) obj;
+                return this.groupId == that.groupId && Arrays.equals(this.context, that.context);
+            }
+            return false;
+        }
+        return false;
+    }
+
+    @Override
+    public SpeculationLog.SpeculationReasonEncoding encode(Supplier<SpeculationLog.SpeculationReasonEncoding> encodingSupplier) {
+        if (encoding == null) {
+            encoding = encodingSupplier.get();
+            encoding.addInt(groupId);
+            for (Object o : context) {
+                if (o == null) {
+                    encoding.addInt(0);
+                } else {
+                    addNonNullObject(encoding, o);
+                }
+            }
+        }
+        return encoding;
+    }
+
+    static void addNonNullObject(SpeculationLog.SpeculationReasonEncoding encoding, Object o) {
+        Class<? extends Object> c = o.getClass();
+        if (c == String.class) {
+            encoding.addString((String) o);
+        } else if (c == Byte.class) {
+            encoding.addByte((Byte) o);
+        } else if (c == Short.class) {
+            encoding.addShort((Short) o);
+        } else if (c == Character.class) {
+            encoding.addShort((Character) o);
+        } else if (c == Integer.class) {
+            encoding.addInt((Integer) o);
+        } else if (c == Long.class) {
+            encoding.addLong((Long) o);
+        } else if (c == Float.class) {
+            encoding.addInt(Float.floatToRawIntBits((Float) o));
+        } else if (c == Double.class) {
+            encoding.addLong(Double.doubleToRawLongBits((Double) o));
+        } else if (o instanceof Enum) {
+            encoding.addInt(((Enum<?>) o).ordinal());
+        } else if (o instanceof ResolvedJavaMethod) {
+            encoding.addMethod((ResolvedJavaMethod) o);
+        } else if (o instanceof ResolvedJavaType) {
+            encoding.addType((ResolvedJavaType) o);
+        } else if (o instanceof ResolvedJavaField) {
+            encoding.addField((ResolvedJavaField) o);
+        } else {
+            throw new IllegalArgumentException("Unsupported type for encoding: " + c.getName());
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return groupId + Arrays.hashCode(this.context);
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%s@%d%s", groupName, groupId, Arrays.toString(context));
+    }
+}
--- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestHotSpotSpeculationLog.java	Thu Oct 24 12:18:32 2019 -0700
+++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestHotSpotSpeculationLog.java	Thu Oct 24 16:58:39 2019 -0700
@@ -78,7 +78,8 @@
     public synchronized void testFailedSpeculations() {
         HotSpotSpeculationLog log = new HotSpotSpeculationLog();
         DummyReason reason1 = new DummyReason("dummy1");
-        DummyReason reason2 = new DummyReason("dummy2");
+        String longName = new String(new char[2000]).replace('\0', 'X');
+        DummyReason reason2 = new DummyReason(longName);
         Assert.assertTrue(log.maySpeculate(reason1));
         Assert.assertTrue(log.maySpeculate(reason2));