< prev index next >
src/share/vm/opto/parse1.cpp
Print this page
rev 9165 : 8141551: C2 can not handle returns with inccompatible interface arrays
Reviewed-by: kvn
*** 989,1005 ****
Node* ret_phi = _gvn.transform( _exits.argument(0) );
if (!_exits.control()->is_top() && _gvn.type(ret_phi)->empty()) {
// 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
{
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");
! }
! #endif
C->record_failure(C2Compiler::retry_class_loading_during_parsing());
}
_exits.push_node(ret_type->basic_type(), ret_phi);
}
// Note: Logic for creating and optimizing the ReturnNode is in Compile.
--- 989,1010 ----
Node* ret_phi = _gvn.transform( _exits.argument(0) );
if (!_exits.control()->is_top() && _gvn.type(ret_phi)->empty()) {
// 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.
! // 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);
! 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.");
+ }
+ }
+ return;
}
_exits.push_node(ret_type->basic_type(), ret_phi);
}
// Note: Logic for creating and optimizing the ReturnNode is in Compile.
*** 2145,2163 ****
// If returning oops to an interface-return, there is a silent free
// cast from oop to interface allowed by the Verifier. Make it explicit
// here.
Node* phi = _exits.argument(0);
const TypeInstPtr *tr = phi->bottom_type()->isa_instptr();
! 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));
}
}
phi->add_req(value);
}
--- 2150,2181 ----
// If returning oops to an interface-return, there is a silent free
// cast from oop to interface allowed by the Verifier. Make it explicit
// here.
Node* phi = _exits.argument(0);
const TypeInstPtr *tr = phi->bottom_type()->isa_instptr();
! 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));
! }
! } else {
! // Also handle returns of oop-arrays to an arrays-of-interface return
! const TypePtr* phi_tp;
! const TypePtr* val_tp;
! Type::get_arrays_base_elements(phi->bottom_type(), value->bottom_type(), &phi_tp, &val_tp);
! if (phi_tp != NULL && val_tp != NULL) {
! const TypeInstPtr *tr = phi_tp->isa_instptr();
! const TypeInstPtr *tp = val_tp->isa_instptr();
! if (tr != NULL && tr->is_loaded() && tr->klass()->is_interface() &&
! tp != NULL && tp->is_loaded() && !tp->klass()->is_interface()) {
! value = _gvn.transform(new CheckCastPPNode(0, value, phi->bottom_type()));
! }
}
}
phi->add_req(value);
}
< prev index next >