8076112: Add @HotSpotIntrinsicCandidate annotation to indicate methods for which Java Runtime has intrinsics
authorzmajo
Fri, 03 Jul 2015 07:25:03 +0200
changeset 31587 e48945b7849c
parent 31586 6e57742d1adb
child 31588 2a864a4a414c
8076112: Add @HotSpotIntrinsicCandidate annotation to indicate methods for which Java Runtime has intrinsics Summary: Annotate possibly intrinsified methods with @HotSpotIntrinsicCandidate. Add checks omitted by intrinsics to the library code. Add CheckIntrinsics flags to check consistency of intrinsics. Reviewed-by: jrose, kvn, thartmann, vlivanov, abuckley, darcy, ascarpino, briangoetz, alanb, aph, dnsimon
hotspot/src/share/vm/c1/c1_GraphBuilder.cpp
hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp
hotspot/src/share/vm/ci/ciMethod.hpp
hotspot/src/share/vm/classfile/classFileParser.cpp
hotspot/src/share/vm/classfile/classFileParser.hpp
hotspot/src/share/vm/classfile/javaClasses.cpp
hotspot/src/share/vm/classfile/vmSymbols.hpp
hotspot/src/share/vm/interpreter/rewriter.cpp
hotspot/src/share/vm/oops/method.hpp
hotspot/src/share/vm/opto/library_call.cpp
hotspot/src/share/vm/runtime/globals.hpp
hotspot/test/compiler/dependencies/MonomorphicObjectCall/TestMonomorphicObjectCall.java
hotspot/test/compiler/dependencies/MonomorphicObjectCall/java/lang/Object.java
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp	Thu Jul 02 17:49:11 2015 -0700
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp	Fri Jul 03 07:25:03 2015 +0200
@@ -3157,6 +3157,9 @@
       // code for the inlined version will be different than the root
       // compiled version which could lead to monotonicity problems on
       // intel.
+      if (CheckIntrinsics && !scope->method()->intrinsic_candidate()) {
+        BAILOUT("failed to inline intrinsic, method not annotated");
+      }
 
       // Set up a stream so that appending instructions works properly.
       ciBytecodeStream s(scope->method());
@@ -3197,6 +3200,9 @@
         // result in the referent being marked live and the reference
         // object removed from the list of discovered references during
         // reference processing.
+        if (CheckIntrinsics && !scope->method()->intrinsic_candidate()) {
+          BAILOUT("failed to inline intrinsic, method not annotated");
+        }
 
         // Also we need intrinsic to prevent commoning reads from this field
         // across safepoint since GC can change its value.
@@ -3317,7 +3323,8 @@
   }
 
   // handle intrinsics
-  if (callee->intrinsic_id() != vmIntrinsics::_none) {
+  if (callee->intrinsic_id() != vmIntrinsics::_none &&
+      (CheckIntrinsics ? callee->intrinsic_candidate() : true)) {
     if (try_inline_intrinsics(callee)) {
       print_inlining(callee, "intrinsic");
       return true;
@@ -4278,7 +4285,7 @@
   assert(result_type->is_int(), "int result");
   Values* args = state()->pop_arguments(callee->arg_size());
 
-  // Pop off some args to speically handle, then push back
+  // Pop off some args to specially handle, then push back
   Value newval = args->pop();
   Value cmpval = args->pop();
   Value offset = args->pop();
--- a/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp	Thu Jul 02 17:49:11 2015 -0700
+++ b/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp	Fri Jul 03 07:25:03 2015 +0200
@@ -1185,7 +1185,6 @@
   vmIntrinsics::ID iid = method()->intrinsic_id();
 
   if (iid == vmIntrinsics::_getClass ||
-      iid ==  vmIntrinsics::_fillInStackTrace ||
       iid == vmIntrinsics::_hashCode)
     return iid;
   else
@@ -1199,10 +1198,6 @@
   case vmIntrinsics::_getClass:
     _return_local = false;
     break;
-  case vmIntrinsics::_fillInStackTrace:
-    arg.set(0); // 'this'
-    set_returned(arg);
-    break;
   case vmIntrinsics::_hashCode:
     // initialized state is correct
     break;
--- a/hotspot/src/share/vm/ci/ciMethod.hpp	Thu Jul 02 17:49:11 2015 -0700
+++ b/hotspot/src/share/vm/ci/ciMethod.hpp	Fri Jul 03 07:25:03 2015 +0200
@@ -178,9 +178,10 @@
   // Code size for inlining decisions.
   int code_size_for_inlining();
 
-  bool caller_sensitive()   const { return get_Method()->caller_sensitive();   }
-  bool force_inline()       const { return get_Method()->force_inline();       }
-  bool dont_inline()        const { return get_Method()->dont_inline();        }
+  bool caller_sensitive()    const { return get_Method()->caller_sensitive();    }
+  bool force_inline()        const { return get_Method()->force_inline();        }
+  bool dont_inline()         const { return get_Method()->dont_inline();         }
+  bool intrinsic_candidate() const { return get_Method()->intrinsic_candidate(); }
 
   int comp_level();
   int highest_osr_comp_level();
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp	Thu Jul 02 17:49:11 2015 -0700
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp	Fri Jul 03 07:25:03 2015 +0200
@@ -1751,6 +1751,10 @@
     if (_location != _in_method)  break;  // only allow for methods
     if (!privileged)              break;  // only allow in privileged code
     return _method_LambdaForm_Hidden;
+  case vmSymbols::VM_SYMBOL_ENUM_NAME(jdk_internal_HotSpotIntrinsicCandidate_signature):
+    if (_location != _in_method)  break;  // only allow for methods
+    if (!privileged)              break;  // only allow in privileged code
+    return _method_HotSpotIntrinsicCandidate;
   case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_Stable_signature):
     if (_location != _in_field)   break;  // only allow for fields
     if (!privileged)              break;  // only allow in privileged code
@@ -1790,6 +1794,8 @@
     m->set_intrinsic_id(vmIntrinsics::_compiledLambdaForm);
   if (has_annotation(_method_LambdaForm_Hidden))
     m->set_hidden(true);
+  if (has_annotation(_method_HotSpotIntrinsicCandidate) && !m->is_synthetic())
+    m->set_intrinsic_candidate(true);
 }
 
 void ClassFileParser::ClassAnnotationCollector::apply_to(instanceKlassHandle k) {
@@ -4132,9 +4138,78 @@
     // (We used to do this lazily, but now we query it in Rewriter,
     // which is eagerly done for every method, so we might as well do it now,
     // when everything is fresh in memory.)
-    if (Method::klass_id_for_intrinsics(this_klass()) != vmSymbols::NO_SID) {
+    vmSymbols::SID klass_id = Method::klass_id_for_intrinsics(this_klass());
+    if (klass_id != vmSymbols::NO_SID) {
       for (int j = 0; j < methods->length(); j++) {
-        methods->at(j)->init_intrinsic_id();
+        Method* method = methods->at(j);
+        method->init_intrinsic_id();
+
+        if (CheckIntrinsics) {
+          // Check if an intrinsic is defined for method 'method',
+          // but the method is not annotated with @HotSpotIntrinsicCandidate.
+          if (method->intrinsic_id() != vmIntrinsics::_none &&
+              !method->intrinsic_candidate()) {
+            tty->print("Compiler intrinsic is defined for method [%s], "
+                       "but the method is not annotated with @HotSpotIntrinsicCandidate.%s",
+                       method->name_and_sig_as_C_string(),
+                       NOT_DEBUG(" Method will not be inlined.") DEBUG_ONLY(" Exiting.")
+                       );
+            tty->cr();
+            DEBUG_ONLY(vm_exit(1));
+          }
+          // Check is the method 'method' is annotated with @HotSpotIntrinsicCandidate,
+          // but there is no intrinsic available for it.
+          if (method->intrinsic_candidate() &&
+              method->intrinsic_id() == vmIntrinsics::_none) {
+            tty->print("Method [%s] is annotated with @HotSpotIntrinsicCandidate, "
+                       "but no compiler intrinsic is defined for the method.%s",
+                       method->name_and_sig_as_C_string(),
+                       NOT_DEBUG("") DEBUG_ONLY(" Exiting.")
+                       );
+            tty->cr();
+            DEBUG_ONLY(vm_exit(1));
+          }
+        }
+      }
+
+      if (CheckIntrinsics) {
+        // Check for orphan methods in the current class. A method m
+        // of a class C is orphan if an intrinsic is defined for method m,
+        // but class C does not declare m.
+
+        for (int id = vmIntrinsics::FIRST_ID; id < (int)vmIntrinsics::ID_LIMIT; id++) {
+          if (id == vmIntrinsics::_compiledLambdaForm) {
+            // The _compiledLamdbdaForm intrinsic is a special marker for bytecode
+            // generated for the JVM from a LambdaForm and therefore no method
+            // is defined for it.
+            continue;
+          }
+
+          if (vmIntrinsics::class_for(vmIntrinsics::ID_from(id)) == klass_id) {
+            // Check if the current class contains a method with the same
+            // name, flags, signature.
+            bool match = false;
+            for (int j = 0; j < methods->length(); j++) {
+              Method* method = methods->at(j);
+              if (id == method->intrinsic_id()) {
+                match = true;
+                break;
+              }
+            }
+
+            if (!match) {
+              char buf[1000];
+              tty->print("Compiler intrinsic is defined for method [%s], "
+                         "but the method is not available in class [%s].%s",
+                         vmIntrinsics::short_name_as_C_string(vmIntrinsics::ID_from(id), buf, sizeof(buf)),
+                         this_klass->name()->as_C_string(),
+                         NOT_DEBUG("") DEBUG_ONLY(" Exiting.")
+                         );
+              tty->cr();
+              DEBUG_ONLY(vm_exit(1));
+            }
+          }
+        }
       }
     }
 
--- a/hotspot/src/share/vm/classfile/classFileParser.hpp	Thu Jul 02 17:49:11 2015 -0700
+++ b/hotspot/src/share/vm/classfile/classFileParser.hpp	Fri Jul 03 07:25:03 2015 +0200
@@ -130,6 +130,7 @@
       _method_InjectedProfile,
       _method_LambdaForm_Compiled,
       _method_LambdaForm_Hidden,
+      _method_HotSpotIntrinsicCandidate,
       _sun_misc_Contended,
       _field_Stable,
       _annotation_LIMIT
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp	Thu Jul 02 17:49:11 2015 -0700
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp	Fri Jul 03 07:25:03 2015 +0200
@@ -1707,8 +1707,7 @@
     // - rest of the stack
 
     if (!skip_fillInStackTrace_check) {
-      if ((method->name() == vmSymbols::fillInStackTrace_name() ||
-           method->name() == vmSymbols::fillInStackTrace0_name()) &&
+      if (method->name() == vmSymbols::fillInStackTrace_name() &&
           throwable->is_a(method->method_holder())) {
         continue;
       }
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp	Thu Jul 02 17:49:11 2015 -0700
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp	Fri Jul 03 07:25:03 2015 +0200
@@ -258,6 +258,8 @@
   /* Type Annotations (JDK 8 and above) */                                                        \
   template(type_annotations_name,                     "typeAnnotations")                          \
                                                                                                   \
+  /* Intrinsic Annotation (JDK 9 and above) */                                                    \
+  template(jdk_internal_HotSpotIntrinsicCandidate_signature, "Ljdk/internal/HotSpotIntrinsicCandidate;") \
                                                                                                   \
   /* Support for JSR 292 & invokedynamic (JDK 1.7 and above) */                                   \
   template(java_lang_invoke_CallSite,                 "java/lang/invoke/CallSite")                \
@@ -345,7 +347,6 @@
   template(dispatch_name,                             "dispatch")                                 \
   template(getSystemClassLoader_name,                 "getSystemClassLoader")                     \
   template(fillInStackTrace_name,                     "fillInStackTrace")                         \
-  template(fillInStackTrace0_name,                    "fillInStackTrace0")                        \
   template(getCause_name,                             "getCause")                                 \
   template(initCause_name,                            "initCause")                                \
   template(setProperty_name,                          "setProperty")                              \
@@ -635,7 +636,43 @@
 // The F_xx is one of the Flags enum; see below.
 //
 // for Emacs: (let ((c-backslash-column 120) (c-backslash-max-column 120)) (c-backslash-region (point) (point-max) nil t))
+//
+//
+// There are two types of intrinsic methods: (1) Library intrinsics and (2) bytecode intrinsics.
+//
+// (1) A library intrinsic method may be replaced with hand-crafted assembly code,
+// with hand-crafted compiler IR, or with a combination of the two. The semantics
+// of the replacement code may differ from the semantics of the replaced code.
+//
+// (2) Bytecode intrinsic methods are not replaced by special code, but they are
+// treated in some other special way by the compiler. For example, the compiler
+// may delay inlining for some String-related intrinsic methods (e.g., some methods
+// defined in the StringBuilder and StringBuffer classes, see
+// Compile::should_delay_string_inlining() for more details).
+//
+// Due to the difference between the semantics of an intrinsic method as defined
+// in the (Java) source code and the semantics of the method as defined
+// by the code in the VM, intrinsic methods must be explicitly marked.
+//
+// Intrinsic methods are marked by the jdk.internal.HotSpotIntrinsicCandidate
+// annotation. If CheckIntrinsics is enabled, the VM performs the following
+// checks when a class C is loaded: (1) all intrinsics defined by the VM for
+// class C are present in the loaded class file and are marked;
+// (2) an intrinsic is defined by the VM for all marked methods of class C.
+//
+// If a mismatch is detected for a method, the VM behaves differently depending
+// on the type of build. A fastdebug build exits and reports an error on a mismatch.
+// A product build will not replace an unmarked library intrinsic method with
+// hand-crafted code, that is, unmarked library intrinsics are treated as ordinary
+// methods in a product build. The special treatment of a bytecode intrinsic method
+// persists even if the method not marked.
+//
+// When adding an intrinsic for a method, please make sure to appropriately
+// annotate the method in the source code. The list below contains all
+// library intrinsics followed by bytecode intrinsics. Please also make sure to
+// add the declaration of the intrinsic to the approriate section of the list.
 #define VM_INTRINSICS_DO(do_intrinsic, do_class, do_name, do_signature, do_alias)                                       \
+  /* (1) Library intrinsics                                                                        */                   \
   do_intrinsic(_hashCode,                 java_lang_Object,       hashCode_name, void_int_signature,             F_R)   \
    do_name(     hashCode_name,                                   "hashCode")                                            \
   do_intrinsic(_getClass,                 java_lang_Object,       getClass_name, void_class_signature,           F_R)   \
@@ -792,12 +829,12 @@
                                                                                                                         \
   do_class(sun_nio_cs_iso8859_1_Encoder,  "sun/nio/cs/ISO_8859_1$Encoder")                                              \
   do_intrinsic(_encodeISOArray,     sun_nio_cs_iso8859_1_Encoder, encodeISOArray_name, encodeISOArray_signature, F_S)   \
-   do_name(     encodeISOArray_name,                             "encodeISOArray")                                      \
+   do_name(     encodeISOArray_name,                             "implEncodeISOArray")                                  \
    do_signature(encodeISOArray_signature,                        "([CI[BII)I")                                          \
                                                                                                                         \
   do_class(java_math_BigInteger,                      "java/math/BigInteger")                                           \
   do_intrinsic(_multiplyToLen,      java_math_BigInteger, multiplyToLen_name, multiplyToLen_signature, F_S)             \
-   do_name(     multiplyToLen_name,                             "multiplyToLen")                                        \
+   do_name(     multiplyToLen_name,                             "implMultiplyToLen")                                    \
    do_signature(multiplyToLen_signature,                        "([II[II[I)[I")                                         \
                                                                                                                         \
   do_intrinsic(_squareToLen, java_math_BigInteger, squareToLen_name, squareToLen_signature, F_S)                        \
@@ -823,21 +860,21 @@
   do_class(com_sun_crypto_provider_aescrypt,      "com/sun/crypto/provider/AESCrypt")                                   \
   do_intrinsic(_aescrypt_encryptBlock, com_sun_crypto_provider_aescrypt, encryptBlock_name, byteArray_int_byteArray_int_signature, F_R)   \
   do_intrinsic(_aescrypt_decryptBlock, com_sun_crypto_provider_aescrypt, decryptBlock_name, byteArray_int_byteArray_int_signature, F_R)   \
-   do_name(     encryptBlock_name,                                 "encryptBlock")                                      \
-   do_name(     decryptBlock_name,                                 "decryptBlock")                                      \
+   do_name(     encryptBlock_name,                                 "implEncryptBlock")                                  \
+   do_name(     decryptBlock_name,                                 "implDecryptBlock")                                  \
    do_signature(byteArray_int_byteArray_int_signature,             "([BI[BI)V")                                         \
                                                                                                                         \
   do_class(com_sun_crypto_provider_cipherBlockChaining,            "com/sun/crypto/provider/CipherBlockChaining")       \
    do_intrinsic(_cipherBlockChaining_encryptAESCrypt, com_sun_crypto_provider_cipherBlockChaining, encrypt_name, byteArray_int_int_byteArray_int_signature, F_R)   \
    do_intrinsic(_cipherBlockChaining_decryptAESCrypt, com_sun_crypto_provider_cipherBlockChaining, decrypt_name, byteArray_int_int_byteArray_int_signature, F_R)   \
-   do_name(     encrypt_name,                                      "encrypt")                                           \
-   do_name(     decrypt_name,                                      "decrypt")                                           \
+   do_name(     encrypt_name,                                      "implEncrypt")                                       \
+   do_name(     decrypt_name,                                      "implDecrypt")                                       \
    do_signature(byteArray_int_int_byteArray_int_signature,         "([BII[BI)I")                                        \
                                                                                                                         \
   /* support for sun.security.provider.SHA */                                                                           \
   do_class(sun_security_provider_sha,                              "sun/security/provider/SHA")                         \
   do_intrinsic(_sha_implCompress, sun_security_provider_sha, implCompress_name, implCompress_signature, F_R)            \
-   do_name(     implCompress_name,                                 "implCompress")                                      \
+   do_name(     implCompress_name,                                 "implCompress0")                                     \
    do_signature(implCompress_signature,                            "([BI)V")                                            \
                                                                                                                         \
   /* support for sun.security.provider.SHA2 */                                                                          \
@@ -851,7 +888,7 @@
   /* support for sun.security.provider.DigestBase */                                                                    \
   do_class(sun_security_provider_digestbase,                       "sun/security/provider/DigestBase")                  \
   do_intrinsic(_digestBase_implCompressMB, sun_security_provider_digestbase, implCompressMB_name, implCompressMB_signature, F_R)   \
-   do_name(     implCompressMB_name,                               "implCompressMultiBlock")                            \
+   do_name(     implCompressMB_name,                               "implCompressMultiBlock0")                           \
    do_signature(implCompressMB_signature,                          "([BII)I")                                           \
                                                                                                                         \
   /* support for com.sun.crypto.provider.GHASH */                                                                       \
@@ -865,17 +902,18 @@
   do_intrinsic(_updateCRC32,               java_util_zip_CRC32,   update_name, int2_int_signature,               F_SN)  \
    do_name(     update_name,                                      "update")                                             \
   do_intrinsic(_updateBytesCRC32,          java_util_zip_CRC32,   updateBytes_name, updateBytes_signature,       F_SN)  \
-   do_name(     updateBytes_name,                                "updateBytes")                                         \
+   do_name(     updateBytes_name,                                "updateBytes0")                                        \
    do_signature(updateBytes_signature,                           "(I[BII)I")                                            \
   do_intrinsic(_updateByteBufferCRC32,     java_util_zip_CRC32,   updateByteBuffer_name, updateByteBuffer_signature, F_SN) \
-   do_name(     updateByteBuffer_name,                           "updateByteBuffer")                                    \
+   do_name(     updateByteBuffer_name,                           "updateByteBuffer0")                                   \
    do_signature(updateByteBuffer_signature,                      "(IJII)I")                                             \
                                                                                                                         \
   /* support for java.util.zip.CRC32C */                                                                                \
   do_class(java_util_zip_CRC32C,          "java/util/zip/CRC32C")                                                       \
-  do_intrinsic(_updateBytesCRC32C,         java_util_zip_CRC32C,  updateBytes_name, updateBytes_signature,       F_S)   \
-  do_intrinsic(_updateDirectByteBufferCRC32C, java_util_zip_CRC32C, updateDirectByteBuffer_name, updateByteBuffer_signature, F_S) \
-   do_name(     updateDirectByteBuffer_name,                     "updateDirectByteBuffer")                              \
+  do_intrinsic(_updateBytesCRC32C,         java_util_zip_CRC32C,  updateBytes_C_name, updateBytes_signature,       F_S) \
+   do_name(     updateBytes_C_name,                               "updateBytes")                                        \
+  do_intrinsic(_updateDirectByteBufferCRC32C, java_util_zip_CRC32C, updateDirectByteBuffer_C_name, updateByteBuffer_signature, F_S) \
+   do_name(    updateDirectByteBuffer_C_name,                     "updateDirectByteBuffer")                             \
                                                                                                                         \
   /* support for sun.misc.Unsafe */                                                                                     \
   do_class(sun_misc_Unsafe,               "sun/misc/Unsafe")                                                            \
@@ -886,12 +924,6 @@
   do_intrinsic(_copyMemory,               sun_misc_Unsafe,        copyMemory_name, copyMemory_signature,         F_RN)  \
    do_name(     copyMemory_name,                                 "copyMemory")                                          \
    do_signature(copyMemory_signature,         "(Ljava/lang/Object;JLjava/lang/Object;JJ)V")                             \
-  do_intrinsic(_park,                     sun_misc_Unsafe,        park_name, park_signature,                     F_RN)  \
-   do_name(     park_name,                                       "park")                                                \
-   do_signature(park_signature,                                  "(ZJ)V")                                               \
-  do_intrinsic(_unpark,                   sun_misc_Unsafe,        unpark_name, unpark_signature,                 F_RN)  \
-   do_name(     unpark_name,                                     "unpark")                                              \
-   do_alias(    unpark_signature,                               /*(LObject;)V*/ object_void_signature)                  \
   do_intrinsic(_loadFence,                sun_misc_Unsafe,        loadFence_name, loadFence_signature,           F_RN)  \
    do_name(     loadFence_name,                                  "loadFence")                                           \
    do_alias(    loadFence_signature,                              void_method_signature)                                \
@@ -1074,11 +1106,15 @@
   do_intrinsic(_getAndSetObject,          sun_misc_Unsafe,        getAndSetObject_name, getAndSetObject_signature,  F_R)\
    do_name(     getAndSetObject_name,                             "getAndSetObject")                                    \
    do_signature(getAndSetObject_signature,                        "(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;" ) \
-    /*== LAST_COMPILER_INLINE*/                                                                                         \
-    /*the compiler does have special inlining code for these; bytecode inline is just fine */                           \
+                                                                                                                        \
+   /* (2) Bytecode intrinsics                                                                        */                 \
                                                                                                                         \
-  do_intrinsic(_fillInStackTrace,         java_lang_Throwable, fillInStackTrace_name, void_throwable_signature,  F_RNY) \
-                                                                                                                          \
+  do_intrinsic(_park,                     sun_misc_Unsafe,        park_name, park_signature,                     F_RN)  \
+   do_name(     park_name,                                       "park")                                                \
+   do_signature(park_signature,                                  "(ZJ)V")                                               \
+  do_intrinsic(_unpark,                   sun_misc_Unsafe,        unpark_name, unpark_signature,                 F_RN)  \
+   do_name(     unpark_name,                                     "unpark")                                              \
+   do_alias(    unpark_signature,                               /*(LObject;)V*/ object_void_signature)                  \
   do_intrinsic(_StringBuilder_void,   java_lang_StringBuilder, object_initializer_name, void_method_signature,     F_R)   \
   do_intrinsic(_StringBuilder_int,    java_lang_StringBuilder, object_initializer_name, int_void_signature,        F_R)   \
   do_intrinsic(_StringBuilder_String, java_lang_StringBuilder, object_initializer_name, string_void_signature,     F_R)   \
--- a/hotspot/src/share/vm/interpreter/rewriter.cpp	Thu Jul 02 17:49:11 2015 -0700
+++ b/hotspot/src/share/vm/interpreter/rewriter.cpp	Fri Jul 03 07:25:03 2015 +0200
@@ -107,7 +107,7 @@
 // more complicated solution is required.  A special return bytecode
 // is used only by Object.<init> to signal the finalization
 // registration point.  Additionally local 0 must be preserved so it's
-// available to pass to the registration function.  For simplicty we
+// available to pass to the registration function.  For simplicity we
 // require that local 0 is never overwritten so it's available as an
 // argument for registration.
 
--- a/hotspot/src/share/vm/oops/method.hpp	Thu Jul 02 17:49:11 2015 -0700
+++ b/hotspot/src/share/vm/oops/method.hpp	Fri Jul 03 07:25:03 2015 +0200
@@ -82,7 +82,8 @@
     _dont_inline          = 1 << 3,
     _hidden               = 1 << 4,
     _has_injected_profile = 1 << 5,
-    _running_emcp         = 1 << 6
+    _running_emcp         = 1 << 6,
+    _intrinsic_candidate  = 1 << 7
   };
   u1 _flags;
 
@@ -815,6 +816,13 @@
     _flags = x ? (_flags | _hidden) : (_flags & ~_hidden);
   }
 
+  bool intrinsic_candidate() {
+    return (_flags & _intrinsic_candidate) != 0;
+  }
+  void set_intrinsic_candidate(bool x) {
+    _flags = x ? (_flags | _intrinsic_candidate) : (_flags & ~_intrinsic_candidate);
+  }
+
   bool has_injected_profile() {
     return (_flags & _has_injected_profile) != 0;
   }
--- a/hotspot/src/share/vm/opto/library_call.cpp	Thu Jul 02 17:49:11 2015 -0700
+++ b/hotspot/src/share/vm/opto/library_call.cpp	Fri Jul 03 07:25:03 2015 +0200
@@ -651,7 +651,8 @@
   const int bci    = kit.bci();
 
   // Try to inline the intrinsic.
-  if (kit.try_to_inline(_last_predicate)) {
+  if ((CheckIntrinsics ? callee->intrinsic_candidate() : true) &&
+      kit.try_to_inline(_last_predicate)) {
     if (C->print_intrinsics() || C->print_inlining()) {
       C->print_inlining(callee, jvms->depth() - 1, bci, is_virtual() ? "(intrinsic, virtual)" : "(intrinsic)");
     }
@@ -672,7 +673,13 @@
   if (C->print_intrinsics() || C->print_inlining()) {
     if (jvms->has_method()) {
       // Not a root compile.
-      const char* msg = is_virtual() ? "failed to inline (intrinsic, virtual)" : "failed to inline (intrinsic)";
+      const char* msg;
+      if (callee->intrinsic_candidate()) {
+        msg = is_virtual() ? "failed to inline (intrinsic, virtual)" : "failed to inline (intrinsic)";
+      } else {
+        msg = is_virtual() ? "failed to inline (intrinsic, virtual), method not annotated"
+                           : "failed to inline (intrinsic), method not annotated";
+      }
       C->print_inlining(callee, jvms->depth() - 1, bci, msg);
     } else {
       // Root compile
@@ -5258,7 +5265,7 @@
 
 //-------------inline_multiplyToLen-----------------------------------
 bool LibraryCallKit::inline_multiplyToLen() {
-  assert(UseMultiplyToLenIntrinsic, "not implementated on this platform");
+  assert(UseMultiplyToLenIntrinsic, "not implemented on this platform");
 
   address stubAddr = StubRoutines::multiplyToLen();
   if (stubAddr == NULL) {
--- a/hotspot/src/share/vm/runtime/globals.hpp	Thu Jul 02 17:49:11 2015 -0700
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Fri Jul 03 07:25:03 2015 +0200
@@ -4120,7 +4120,16 @@
                                                                             \
   product_pd(bool, PreserveFramePointer,                                    \
              "Use the FP register for holding the frame pointer "           \
-             "and not as a general purpose register.")
+             "and not as a general purpose register.")                      \
+                                                                            \
+  diagnostic(bool, CheckIntrinsics, trueInDebug,                            \
+             "When a class C is loaded, check that "                        \
+             "(1) all intrinsics defined by the VM for class C are present "\
+             "in the loaded class file and are marked with the "            \
+             "@HotSpotIntrinsicCandidate annotation and also that "         \
+             "(2) there is an intrinsic registered for all loaded methods " \
+             "that are annotated with the @HotSpotIntrinsicCandidate "      \
+             "annotation.")
 
 /*
  *  Macros for factoring of globals
--- a/hotspot/test/compiler/dependencies/MonomorphicObjectCall/TestMonomorphicObjectCall.java	Thu Jul 02 17:49:11 2015 -0700
+++ b/hotspot/test/compiler/dependencies/MonomorphicObjectCall/TestMonomorphicObjectCall.java	Fri Jul 03 07:25:03 2015 +0200
@@ -34,6 +34,7 @@
  * @library /testlibrary
  * @modules java.base/sun.misc
  *          java.management
+ *          java.base/jdk.internal
  * @compile -XDignore.symbol.file java/lang/Object.java TestMonomorphicObjectCall.java
  * @run main TestMonomorphicObjectCall
  */
--- a/hotspot/test/compiler/dependencies/MonomorphicObjectCall/java/lang/Object.java	Thu Jul 02 17:49:11 2015 -0700
+++ b/hotspot/test/compiler/dependencies/MonomorphicObjectCall/java/lang/Object.java	Fri Jul 03 07:25:03 2015 +0200
@@ -25,25 +25,33 @@
 
 package java.lang;
 
+import jdk.internal.HotSpotIntrinsicCandidate;
+
 /**
  * Slightly modified version of java.lang.Object that replaces
  * finalize() by finalizeObject() to avoid overriding in subclasses.
  */
 public class Object {
 
+    @HotSpotIntrinsicCandidate
+    public Object() {}
+
     private static native void registerNatives();
     static {
         registerNatives();
     }
 
+    @HotSpotIntrinsicCandidate
     public final native Class<?> getClass();
 
+    @HotSpotIntrinsicCandidate
     public native int hashCode();
 
     public boolean equals(Object obj) {
         return (this == obj);
     }
 
+    @HotSpotIntrinsicCandidate
     protected native Object clone() throws CloneNotSupportedException;
 
     public String toString() {