8076112: Add @HotSpotIntrinsicCandidate annotation to indicate methods for which Java Runtime has intrinsics
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
This commit is contained in:
parent
34616cd876
commit
9245cdc214
@ -3157,6 +3157,9 @@ GraphBuilder::GraphBuilder(Compilation* compilation, IRScope* scope)
|
|||||||
// code for the inlined version will be different than the root
|
// code for the inlined version will be different than the root
|
||||||
// compiled version which could lead to monotonicity problems on
|
// compiled version which could lead to monotonicity problems on
|
||||||
// intel.
|
// 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.
|
// Set up a stream so that appending instructions works properly.
|
||||||
ciBytecodeStream s(scope->method());
|
ciBytecodeStream s(scope->method());
|
||||||
@ -3197,6 +3200,9 @@ GraphBuilder::GraphBuilder(Compilation* compilation, IRScope* scope)
|
|||||||
// result in the referent being marked live and the reference
|
// result in the referent being marked live and the reference
|
||||||
// object removed from the list of discovered references during
|
// object removed from the list of discovered references during
|
||||||
// reference processing.
|
// 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
|
// Also we need intrinsic to prevent commoning reads from this field
|
||||||
// across safepoint since GC can change its value.
|
// across safepoint since GC can change its value.
|
||||||
@ -3317,7 +3323,8 @@ bool GraphBuilder::try_inline(ciMethod* callee, bool holder_known, Bytecodes::Co
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle intrinsics
|
// handle intrinsics
|
||||||
if (callee->intrinsic_id() != vmIntrinsics::_none) {
|
if (callee->intrinsic_id() != vmIntrinsics::_none &&
|
||||||
|
(CheckIntrinsics ? callee->intrinsic_candidate() : true)) {
|
||||||
if (try_inline_intrinsics(callee)) {
|
if (try_inline_intrinsics(callee)) {
|
||||||
print_inlining(callee, "intrinsic");
|
print_inlining(callee, "intrinsic");
|
||||||
return true;
|
return true;
|
||||||
@ -4278,7 +4285,7 @@ void GraphBuilder::append_unsafe_CAS(ciMethod* callee) {
|
|||||||
assert(result_type->is_int(), "int result");
|
assert(result_type->is_int(), "int result");
|
||||||
Values* args = state()->pop_arguments(callee->arg_size());
|
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 newval = args->pop();
|
||||||
Value cmpval = args->pop();
|
Value cmpval = args->pop();
|
||||||
Value offset = args->pop();
|
Value offset = args->pop();
|
||||||
|
@ -1185,7 +1185,6 @@ vmIntrinsics::ID BCEscapeAnalyzer::known_intrinsic() {
|
|||||||
vmIntrinsics::ID iid = method()->intrinsic_id();
|
vmIntrinsics::ID iid = method()->intrinsic_id();
|
||||||
|
|
||||||
if (iid == vmIntrinsics::_getClass ||
|
if (iid == vmIntrinsics::_getClass ||
|
||||||
iid == vmIntrinsics::_fillInStackTrace ||
|
|
||||||
iid == vmIntrinsics::_hashCode)
|
iid == vmIntrinsics::_hashCode)
|
||||||
return iid;
|
return iid;
|
||||||
else
|
else
|
||||||
@ -1199,10 +1198,6 @@ bool BCEscapeAnalyzer::compute_escape_for_intrinsic(vmIntrinsics::ID iid) {
|
|||||||
case vmIntrinsics::_getClass:
|
case vmIntrinsics::_getClass:
|
||||||
_return_local = false;
|
_return_local = false;
|
||||||
break;
|
break;
|
||||||
case vmIntrinsics::_fillInStackTrace:
|
|
||||||
arg.set(0); // 'this'
|
|
||||||
set_returned(arg);
|
|
||||||
break;
|
|
||||||
case vmIntrinsics::_hashCode:
|
case vmIntrinsics::_hashCode:
|
||||||
// initialized state is correct
|
// initialized state is correct
|
||||||
break;
|
break;
|
||||||
|
@ -181,6 +181,7 @@ class ciMethod : public ciMetadata {
|
|||||||
bool caller_sensitive() const { return get_Method()->caller_sensitive(); }
|
bool caller_sensitive() const { return get_Method()->caller_sensitive(); }
|
||||||
bool force_inline() const { return get_Method()->force_inline(); }
|
bool force_inline() const { return get_Method()->force_inline(); }
|
||||||
bool dont_inline() const { return get_Method()->dont_inline(); }
|
bool dont_inline() const { return get_Method()->dont_inline(); }
|
||||||
|
bool intrinsic_candidate() const { return get_Method()->intrinsic_candidate(); }
|
||||||
|
|
||||||
int comp_level();
|
int comp_level();
|
||||||
int highest_osr_comp_level();
|
int highest_osr_comp_level();
|
||||||
|
@ -1751,6 +1751,10 @@ ClassFileParser::AnnotationCollector::annotation_index(ClassLoaderData* loader_d
|
|||||||
if (_location != _in_method) break; // only allow for methods
|
if (_location != _in_method) break; // only allow for methods
|
||||||
if (!privileged) break; // only allow in privileged code
|
if (!privileged) break; // only allow in privileged code
|
||||||
return _method_LambdaForm_Hidden;
|
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):
|
case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_Stable_signature):
|
||||||
if (_location != _in_field) break; // only allow for fields
|
if (_location != _in_field) break; // only allow for fields
|
||||||
if (!privileged) break; // only allow in privileged code
|
if (!privileged) break; // only allow in privileged code
|
||||||
@ -1790,6 +1794,8 @@ void ClassFileParser::MethodAnnotationCollector::apply_to(methodHandle m) {
|
|||||||
m->set_intrinsic_id(vmIntrinsics::_compiledLambdaForm);
|
m->set_intrinsic_id(vmIntrinsics::_compiledLambdaForm);
|
||||||
if (has_annotation(_method_LambdaForm_Hidden))
|
if (has_annotation(_method_LambdaForm_Hidden))
|
||||||
m->set_hidden(true);
|
m->set_hidden(true);
|
||||||
|
if (has_annotation(_method_HotSpotIntrinsicCandidate) && !m->is_synthetic())
|
||||||
|
m->set_intrinsic_candidate(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassFileParser::ClassAnnotationCollector::apply_to(instanceKlassHandle k) {
|
void ClassFileParser::ClassAnnotationCollector::apply_to(instanceKlassHandle k) {
|
||||||
@ -4132,9 +4138,78 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
|||||||
// (We used to do this lazily, but now we query it in Rewriter,
|
// (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,
|
// which is eagerly done for every method, so we might as well do it now,
|
||||||
// when everything is fresh in memory.)
|
// 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++) {
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,6 +130,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
|||||||
_method_InjectedProfile,
|
_method_InjectedProfile,
|
||||||
_method_LambdaForm_Compiled,
|
_method_LambdaForm_Compiled,
|
||||||
_method_LambdaForm_Hidden,
|
_method_LambdaForm_Hidden,
|
||||||
|
_method_HotSpotIntrinsicCandidate,
|
||||||
_sun_misc_Contended,
|
_sun_misc_Contended,
|
||||||
_field_Stable,
|
_field_Stable,
|
||||||
_annotation_LIMIT
|
_annotation_LIMIT
|
||||||
|
@ -1707,8 +1707,7 @@ void java_lang_Throwable::fill_in_stack_trace(Handle throwable, methodHandle met
|
|||||||
// - rest of the stack
|
// - rest of the stack
|
||||||
|
|
||||||
if (!skip_fillInStackTrace_check) {
|
if (!skip_fillInStackTrace_check) {
|
||||||
if ((method->name() == vmSymbols::fillInStackTrace_name() ||
|
if (method->name() == vmSymbols::fillInStackTrace_name() &&
|
||||||
method->name() == vmSymbols::fillInStackTrace0_name()) &&
|
|
||||||
throwable->is_a(method->method_holder())) {
|
throwable->is_a(method->method_holder())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -258,6 +258,8 @@
|
|||||||
/* Type Annotations (JDK 8 and above) */ \
|
/* Type Annotations (JDK 8 and above) */ \
|
||||||
template(type_annotations_name, "typeAnnotations") \
|
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) */ \
|
/* Support for JSR 292 & invokedynamic (JDK 1.7 and above) */ \
|
||||||
template(java_lang_invoke_CallSite, "java/lang/invoke/CallSite") \
|
template(java_lang_invoke_CallSite, "java/lang/invoke/CallSite") \
|
||||||
@ -345,7 +347,6 @@
|
|||||||
template(dispatch_name, "dispatch") \
|
template(dispatch_name, "dispatch") \
|
||||||
template(getSystemClassLoader_name, "getSystemClassLoader") \
|
template(getSystemClassLoader_name, "getSystemClassLoader") \
|
||||||
template(fillInStackTrace_name, "fillInStackTrace") \
|
template(fillInStackTrace_name, "fillInStackTrace") \
|
||||||
template(fillInStackTrace0_name, "fillInStackTrace0") \
|
|
||||||
template(getCause_name, "getCause") \
|
template(getCause_name, "getCause") \
|
||||||
template(initCause_name, "initCause") \
|
template(initCause_name, "initCause") \
|
||||||
template(setProperty_name, "setProperty") \
|
template(setProperty_name, "setProperty") \
|
||||||
@ -635,7 +636,43 @@
|
|||||||
// The F_xx is one of the Flags enum; see below.
|
// 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))
|
// 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) \
|
#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_intrinsic(_hashCode, java_lang_Object, hashCode_name, void_int_signature, F_R) \
|
||||||
do_name( hashCode_name, "hashCode") \
|
do_name( hashCode_name, "hashCode") \
|
||||||
do_intrinsic(_getClass, java_lang_Object, getClass_name, void_class_signature, F_R) \
|
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_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_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_signature(encodeISOArray_signature, "([CI[BII)I") \
|
||||||
\
|
\
|
||||||
do_class(java_math_BigInteger, "java/math/BigInteger") \
|
do_class(java_math_BigInteger, "java/math/BigInteger") \
|
||||||
do_intrinsic(_multiplyToLen, java_math_BigInteger, multiplyToLen_name, multiplyToLen_signature, F_S) \
|
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_signature(multiplyToLen_signature, "([II[II[I)[I") \
|
||||||
\
|
\
|
||||||
do_intrinsic(_squareToLen, java_math_BigInteger, squareToLen_name, squareToLen_signature, F_S) \
|
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_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_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_intrinsic(_aescrypt_decryptBlock, com_sun_crypto_provider_aescrypt, decryptBlock_name, byteArray_int_byteArray_int_signature, F_R) \
|
||||||
do_name( encryptBlock_name, "encryptBlock") \
|
do_name( encryptBlock_name, "implEncryptBlock") \
|
||||||
do_name( decryptBlock_name, "decryptBlock") \
|
do_name( decryptBlock_name, "implDecryptBlock") \
|
||||||
do_signature(byteArray_int_byteArray_int_signature, "([BI[BI)V") \
|
do_signature(byteArray_int_byteArray_int_signature, "([BI[BI)V") \
|
||||||
\
|
\
|
||||||
do_class(com_sun_crypto_provider_cipherBlockChaining, "com/sun/crypto/provider/CipherBlockChaining") \
|
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_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_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( encrypt_name, "implEncrypt") \
|
||||||
do_name( decrypt_name, "decrypt") \
|
do_name( decrypt_name, "implDecrypt") \
|
||||||
do_signature(byteArray_int_int_byteArray_int_signature, "([BII[BI)I") \
|
do_signature(byteArray_int_int_byteArray_int_signature, "([BII[BI)I") \
|
||||||
\
|
\
|
||||||
/* support for sun.security.provider.SHA */ \
|
/* support for sun.security.provider.SHA */ \
|
||||||
do_class(sun_security_provider_sha, "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_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") \
|
do_signature(implCompress_signature, "([BI)V") \
|
||||||
\
|
\
|
||||||
/* support for sun.security.provider.SHA2 */ \
|
/* support for sun.security.provider.SHA2 */ \
|
||||||
@ -851,7 +888,7 @@
|
|||||||
/* support for sun.security.provider.DigestBase */ \
|
/* support for sun.security.provider.DigestBase */ \
|
||||||
do_class(sun_security_provider_digestbase, "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_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") \
|
do_signature(implCompressMB_signature, "([BII)I") \
|
||||||
\
|
\
|
||||||
/* support for com.sun.crypto.provider.GHASH */ \
|
/* 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_intrinsic(_updateCRC32, java_util_zip_CRC32, update_name, int2_int_signature, F_SN) \
|
||||||
do_name( update_name, "update") \
|
do_name( update_name, "update") \
|
||||||
do_intrinsic(_updateBytesCRC32, java_util_zip_CRC32, updateBytes_name, updateBytes_signature, F_SN) \
|
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_signature(updateBytes_signature, "(I[BII)I") \
|
||||||
do_intrinsic(_updateByteBufferCRC32, java_util_zip_CRC32, updateByteBuffer_name, updateByteBuffer_signature, F_SN) \
|
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") \
|
do_signature(updateByteBuffer_signature, "(IJII)I") \
|
||||||
\
|
\
|
||||||
/* support for java.util.zip.CRC32C */ \
|
/* support for java.util.zip.CRC32C */ \
|
||||||
do_class(java_util_zip_CRC32C, "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(_updateBytesCRC32C, java_util_zip_CRC32C, updateBytes_C_name, updateBytes_signature, F_S) \
|
||||||
do_intrinsic(_updateDirectByteBufferCRC32C, java_util_zip_CRC32C, updateDirectByteBuffer_name, updateByteBuffer_signature, F_S) \
|
do_name( updateBytes_C_name, "updateBytes") \
|
||||||
do_name( updateDirectByteBuffer_name, "updateDirectByteBuffer") \
|
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 */ \
|
/* support for sun.misc.Unsafe */ \
|
||||||
do_class(sun_misc_Unsafe, "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_intrinsic(_copyMemory, sun_misc_Unsafe, copyMemory_name, copyMemory_signature, F_RN) \
|
||||||
do_name( copyMemory_name, "copyMemory") \
|
do_name( copyMemory_name, "copyMemory") \
|
||||||
do_signature(copyMemory_signature, "(Ljava/lang/Object;JLjava/lang/Object;JJ)V") \
|
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_intrinsic(_loadFence, sun_misc_Unsafe, loadFence_name, loadFence_signature, F_RN) \
|
||||||
do_name( loadFence_name, "loadFence") \
|
do_name( loadFence_name, "loadFence") \
|
||||||
do_alias( loadFence_signature, void_method_signature) \
|
do_alias( loadFence_signature, void_method_signature) \
|
||||||
@ -1074,11 +1106,15 @@
|
|||||||
do_intrinsic(_getAndSetObject, sun_misc_Unsafe, getAndSetObject_name, getAndSetObject_signature, F_R)\
|
do_intrinsic(_getAndSetObject, sun_misc_Unsafe, getAndSetObject_name, getAndSetObject_signature, F_R)\
|
||||||
do_name( getAndSetObject_name, "getAndSetObject") \
|
do_name( getAndSetObject_name, "getAndSetObject") \
|
||||||
do_signature(getAndSetObject_signature, "(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;" ) \
|
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 */ \
|
|
||||||
\
|
\
|
||||||
do_intrinsic(_fillInStackTrace, java_lang_Throwable, fillInStackTrace_name, void_throwable_signature, F_RNY) \
|
/* (2) Bytecode intrinsics */ \
|
||||||
\
|
\
|
||||||
|
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_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_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) \
|
do_intrinsic(_StringBuilder_String, java_lang_StringBuilder, object_initializer_name, string_void_signature, F_R) \
|
||||||
|
@ -107,7 +107,7 @@ void Rewriter::make_constant_pool_cache(TRAPS) {
|
|||||||
// more complicated solution is required. A special return bytecode
|
// more complicated solution is required. A special return bytecode
|
||||||
// is used only by Object.<init> to signal the finalization
|
// is used only by Object.<init> to signal the finalization
|
||||||
// registration point. Additionally local 0 must be preserved so it's
|
// 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
|
// require that local 0 is never overwritten so it's available as an
|
||||||
// argument for registration.
|
// argument for registration.
|
||||||
|
|
||||||
|
@ -82,7 +82,8 @@ class Method : public Metadata {
|
|||||||
_dont_inline = 1 << 3,
|
_dont_inline = 1 << 3,
|
||||||
_hidden = 1 << 4,
|
_hidden = 1 << 4,
|
||||||
_has_injected_profile = 1 << 5,
|
_has_injected_profile = 1 << 5,
|
||||||
_running_emcp = 1 << 6
|
_running_emcp = 1 << 6,
|
||||||
|
_intrinsic_candidate = 1 << 7
|
||||||
};
|
};
|
||||||
u1 _flags;
|
u1 _flags;
|
||||||
|
|
||||||
@ -815,6 +816,13 @@ class Method : public Metadata {
|
|||||||
_flags = x ? (_flags | _hidden) : (_flags & ~_hidden);
|
_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() {
|
bool has_injected_profile() {
|
||||||
return (_flags & _has_injected_profile) != 0;
|
return (_flags & _has_injected_profile) != 0;
|
||||||
}
|
}
|
||||||
|
@ -651,7 +651,8 @@ JVMState* LibraryIntrinsic::generate(JVMState* jvms) {
|
|||||||
const int bci = kit.bci();
|
const int bci = kit.bci();
|
||||||
|
|
||||||
// Try to inline the intrinsic.
|
// 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()) {
|
if (C->print_intrinsics() || C->print_inlining()) {
|
||||||
C->print_inlining(callee, jvms->depth() - 1, bci, is_virtual() ? "(intrinsic, virtual)" : "(intrinsic)");
|
C->print_inlining(callee, jvms->depth() - 1, bci, is_virtual() ? "(intrinsic, virtual)" : "(intrinsic)");
|
||||||
}
|
}
|
||||||
@ -672,7 +673,13 @@ JVMState* LibraryIntrinsic::generate(JVMState* jvms) {
|
|||||||
if (C->print_intrinsics() || C->print_inlining()) {
|
if (C->print_intrinsics() || C->print_inlining()) {
|
||||||
if (jvms->has_method()) {
|
if (jvms->has_method()) {
|
||||||
// Not a root compile.
|
// 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);
|
C->print_inlining(callee, jvms->depth() - 1, bci, msg);
|
||||||
} else {
|
} else {
|
||||||
// Root compile
|
// Root compile
|
||||||
@ -5258,7 +5265,7 @@ bool LibraryCallKit::inline_encodeISOArray() {
|
|||||||
|
|
||||||
//-------------inline_multiplyToLen-----------------------------------
|
//-------------inline_multiplyToLen-----------------------------------
|
||||||
bool LibraryCallKit::inline_multiplyToLen() {
|
bool LibraryCallKit::inline_multiplyToLen() {
|
||||||
assert(UseMultiplyToLenIntrinsic, "not implementated on this platform");
|
assert(UseMultiplyToLenIntrinsic, "not implemented on this platform");
|
||||||
|
|
||||||
address stubAddr = StubRoutines::multiplyToLen();
|
address stubAddr = StubRoutines::multiplyToLen();
|
||||||
if (stubAddr == NULL) {
|
if (stubAddr == NULL) {
|
||||||
|
@ -4120,7 +4120,16 @@ public:
|
|||||||
\
|
\
|
||||||
product_pd(bool, PreserveFramePointer, \
|
product_pd(bool, PreserveFramePointer, \
|
||||||
"Use the FP register for holding the frame pointer " \
|
"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
|
* Macros for factoring of globals
|
||||||
|
@ -34,6 +34,7 @@ import jdk.test.lib.*;
|
|||||||
* @library /testlibrary
|
* @library /testlibrary
|
||||||
* @modules java.base/sun.misc
|
* @modules java.base/sun.misc
|
||||||
* java.management
|
* java.management
|
||||||
|
* java.base/jdk.internal
|
||||||
* @compile -XDignore.symbol.file java/lang/Object.java TestMonomorphicObjectCall.java
|
* @compile -XDignore.symbol.file java/lang/Object.java TestMonomorphicObjectCall.java
|
||||||
* @run main TestMonomorphicObjectCall
|
* @run main TestMonomorphicObjectCall
|
||||||
*/
|
*/
|
||||||
|
@ -25,25 +25,33 @@
|
|||||||
|
|
||||||
package java.lang;
|
package java.lang;
|
||||||
|
|
||||||
|
import jdk.internal.HotSpotIntrinsicCandidate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Slightly modified version of java.lang.Object that replaces
|
* Slightly modified version of java.lang.Object that replaces
|
||||||
* finalize() by finalizeObject() to avoid overriding in subclasses.
|
* finalize() by finalizeObject() to avoid overriding in subclasses.
|
||||||
*/
|
*/
|
||||||
public class Object {
|
public class Object {
|
||||||
|
|
||||||
|
@HotSpotIntrinsicCandidate
|
||||||
|
public Object() {}
|
||||||
|
|
||||||
private static native void registerNatives();
|
private static native void registerNatives();
|
||||||
static {
|
static {
|
||||||
registerNatives();
|
registerNatives();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@HotSpotIntrinsicCandidate
|
||||||
public final native Class<?> getClass();
|
public final native Class<?> getClass();
|
||||||
|
|
||||||
|
@HotSpotIntrinsicCandidate
|
||||||
public native int hashCode();
|
public native int hashCode();
|
||||||
|
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
return (this == obj);
|
return (this == obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@HotSpotIntrinsicCandidate
|
||||||
protected native Object clone() throws CloneNotSupportedException;
|
protected native Object clone() throws CloneNotSupportedException;
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
Loading…
Reference in New Issue
Block a user