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:
Zoltan Majo 2015-07-03 07:25:03 +02:00
parent 34616cd876
commit 9245cdc214
13 changed files with 191 additions and 44 deletions

View file

@ -1751,6 +1751,10 @@ ClassFileParser::AnnotationCollector::annotation_index(ClassLoaderData* loader_d
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 @@ void ClassFileParser::MethodAnnotationCollector::apply_to(methodHandle m) {
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 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
// (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));
}
}
}
}
}