8141551: C2 can not handle returns with inccompatible interface arrays

Reviewed-by: kvn
This commit is contained in:
Volker Simonis 2015-11-16 14:19:10 +01:00
parent f6cb49ba48
commit 350b04eab2
5 changed files with 438 additions and 19 deletions

View file

@ -988,13 +988,18 @@ void Parse::do_exits() {
// In case of concurrent class loading, the type we set for the
// ret_phi in build_exits() may have been too optimistic and the
// ret_phi may be top now.
#ifdef ASSERT
// Otherwise, we've encountered an error and have to mark the method as
// not compilable. Just using an assertion instead would be dangerous
// as this could lead to an infinite compile loop in non-debug builds.
{
MutexLockerEx ml(Compile_lock, Mutex::_no_safepoint_check_flag);
assert(ret_type->isa_ptr() && C->env()->system_dictionary_modification_counter_changed(), "return value must be well defined");
if (C->env()->system_dictionary_modification_counter_changed()) {
C->record_failure(C2Compiler::retry_class_loading_during_parsing());
} else {
C->record_method_not_compilable("Can't determine return type.");
}
}
#endif
C->record_failure(C2Compiler::retry_class_loading_during_parsing());
return;
}
_exits.push_node(ret_type->basic_type(), ret_phi);
}
@ -2144,15 +2149,24 @@ void Parse::return_current(Node* value) {
// here.
Node* phi = _exits.argument(0);
const TypeInstPtr *tr = phi->bottom_type()->isa_instptr();
if( tr && tr->klass()->is_loaded() &&
tr->klass()->is_interface() ) {
if (tr && tr->klass()->is_loaded() &&
tr->klass()->is_interface()) {
const TypeInstPtr *tp = value->bottom_type()->isa_instptr();
if (tp && tp->klass()->is_loaded() &&
!tp->klass()->is_interface()) {
// sharpen the type eagerly; this eases certain assert checking
if (tp->higher_equal(TypeInstPtr::NOTNULL))
tr = tr->join_speculative(TypeInstPtr::NOTNULL)->is_instptr();
value = _gvn.transform(new CheckCastPPNode(0,value,tr));
value = _gvn.transform(new CheckCastPPNode(0, value, tr));
}
} else {
// Also handle returns of oop-arrays to an arrays-of-interface return
const TypeInstPtr* phi_tip;
const TypeInstPtr* val_tip;
Type::get_arrays_base_elements(phi->bottom_type(), value->bottom_type(), &phi_tip, &val_tip);
if (phi_tip != NULL && phi_tip->is_loaded() && phi_tip->klass()->is_interface() &&
val_tip != NULL && val_tip->is_loaded() && !val_tip->klass()->is_interface()) {
value = _gvn.transform(new CheckCastPPNode(0, value, phi->bottom_type()));
}
}
phi->add_req(value);