提交 99f74d4a 编写于 作者: Z zmajo

8175340: Possible invalid memory accesses due to ciMethodData::bci_to_data() returning NULL

Summary: Check values returned by ciMethodData::bci_to_data() where necessary.
Reviewed-by: kvn
上级 54ee327c
...@@ -1530,7 +1530,7 @@ void GraphBuilder::method_return(Value x) { ...@@ -1530,7 +1530,7 @@ void GraphBuilder::method_return(Value x) {
ciMethod* caller = state()->scope()->method(); ciMethod* caller = state()->scope()->method();
ciMethodData* md = caller->method_data_or_null(); ciMethodData* md = caller->method_data_or_null();
ciProfileData* data = md->bci_to_data(invoke_bci); ciProfileData* data = md->bci_to_data(invoke_bci);
if (data->is_CallTypeData() || data->is_VirtualCallTypeData()) { if (data != NULL && (data->is_CallTypeData() || data->is_VirtualCallTypeData())) {
bool has_return = data->is_CallTypeData() ? ((ciCallTypeData*)data)->has_return() : ((ciVirtualCallTypeData*)data)->has_return(); bool has_return = data->is_CallTypeData() ? ((ciCallTypeData*)data)->has_return() : ((ciVirtualCallTypeData*)data)->has_return();
// May not be true in case of an inlined call through a method handle intrinsic. // May not be true in case of an inlined call through a method handle intrinsic.
if (has_return) { if (has_return) {
...@@ -1747,7 +1747,7 @@ Values* GraphBuilder::args_list_for_profiling(ciMethod* target, int& start, bool ...@@ -1747,7 +1747,7 @@ Values* GraphBuilder::args_list_for_profiling(ciMethod* target, int& start, bool
start = has_receiver ? 1 : 0; start = has_receiver ? 1 : 0;
if (profile_arguments()) { if (profile_arguments()) {
ciProfileData* data = method()->method_data()->bci_to_data(bci()); ciProfileData* data = method()->method_data()->bci_to_data(bci());
if (data->is_CallTypeData() || data->is_VirtualCallTypeData()) { if (data != NULL && (data->is_CallTypeData() || data->is_VirtualCallTypeData())) {
n = data->is_CallTypeData() ? data->as_CallTypeData()->number_of_arguments() : data->as_VirtualCallTypeData()->number_of_arguments(); n = data->is_CallTypeData() ? data->as_CallTypeData()->number_of_arguments() : data->as_VirtualCallTypeData()->number_of_arguments();
} }
} }
...@@ -4465,7 +4465,7 @@ void GraphBuilder::profile_return_type(Value ret, ciMethod* callee, ciMethod* m, ...@@ -4465,7 +4465,7 @@ void GraphBuilder::profile_return_type(Value ret, ciMethod* callee, ciMethod* m,
} }
ciMethodData* md = m->method_data_or_null(); ciMethodData* md = m->method_data_or_null();
ciProfileData* data = md->bci_to_data(invoke_bci); ciProfileData* data = md->bci_to_data(invoke_bci);
if (data->is_CallTypeData() || data->is_VirtualCallTypeData()) { if (data != NULL && (data->is_CallTypeData() || data->is_VirtualCallTypeData())) {
append(new ProfileReturnType(m , invoke_bci, callee, ret)); append(new ProfileReturnType(m , invoke_bci, callee, ret));
} }
} }
......
...@@ -3185,50 +3185,52 @@ void LIRGenerator::profile_arguments(ProfileCall* x) { ...@@ -3185,50 +3185,52 @@ void LIRGenerator::profile_arguments(ProfileCall* x) {
int bci = x->bci_of_invoke(); int bci = x->bci_of_invoke();
ciMethodData* md = x->method()->method_data_or_null(); ciMethodData* md = x->method()->method_data_or_null();
ciProfileData* data = md->bci_to_data(bci); ciProfileData* data = md->bci_to_data(bci);
if ((data->is_CallTypeData() && data->as_CallTypeData()->has_arguments()) || if (data != NULL) {
(data->is_VirtualCallTypeData() && data->as_VirtualCallTypeData()->has_arguments())) { if ((data->is_CallTypeData() && data->as_CallTypeData()->has_arguments()) ||
ByteSize extra = data->is_CallTypeData() ? CallTypeData::args_data_offset() : VirtualCallTypeData::args_data_offset(); (data->is_VirtualCallTypeData() && data->as_VirtualCallTypeData()->has_arguments())) {
int base_offset = md->byte_offset_of_slot(data, extra); ByteSize extra = data->is_CallTypeData() ? CallTypeData::args_data_offset() : VirtualCallTypeData::args_data_offset();
LIR_Opr mdp = LIR_OprFact::illegalOpr; int base_offset = md->byte_offset_of_slot(data, extra);
ciTypeStackSlotEntries* args = data->is_CallTypeData() ? ((ciCallTypeData*)data)->args() : ((ciVirtualCallTypeData*)data)->args(); LIR_Opr mdp = LIR_OprFact::illegalOpr;
ciTypeStackSlotEntries* args = data->is_CallTypeData() ? ((ciCallTypeData*)data)->args() : ((ciVirtualCallTypeData*)data)->args();
Bytecodes::Code bc = x->method()->java_code_at_bci(bci);
int start = 0; Bytecodes::Code bc = x->method()->java_code_at_bci(bci);
int stop = data->is_CallTypeData() ? ((ciCallTypeData*)data)->number_of_arguments() : ((ciVirtualCallTypeData*)data)->number_of_arguments(); int start = 0;
if (x->callee()->is_loaded() && x->callee()->is_static() && Bytecodes::has_receiver(bc)) { int stop = data->is_CallTypeData() ? ((ciCallTypeData*)data)->number_of_arguments() : ((ciVirtualCallTypeData*)data)->number_of_arguments();
// first argument is not profiled at call (method handle invoke) if (x->callee()->is_loaded() && x->callee()->is_static() && Bytecodes::has_receiver(bc)) {
assert(x->method()->raw_code_at_bci(bci) == Bytecodes::_invokehandle, "invokehandle expected"); // first argument is not profiled at call (method handle invoke)
start = 1; assert(x->method()->raw_code_at_bci(bci) == Bytecodes::_invokehandle, "invokehandle expected");
} start = 1;
ciSignature* callee_signature = x->callee()->signature();
// method handle call to virtual method
bool has_receiver = x->callee()->is_loaded() && !x->callee()->is_static() && !Bytecodes::has_receiver(bc);
ciSignatureStream callee_signature_stream(callee_signature, has_receiver ? x->callee()->holder() : NULL);
bool ignored_will_link;
ciSignature* signature_at_call = NULL;
x->method()->get_method_at_bci(bci, ignored_will_link, &signature_at_call);
ciSignatureStream signature_at_call_stream(signature_at_call);
// if called through method handle invoke, some arguments may have been popped
for (int i = 0; i < stop && i+start < x->nb_profiled_args(); i++) {
int off = in_bytes(TypeEntriesAtCall::argument_type_offset(i)) - in_bytes(TypeEntriesAtCall::args_data_offset());
ciKlass* exact = profile_type(md, base_offset, off,
args->type(i), x->profiled_arg_at(i+start), mdp,
!x->arg_needs_null_check(i+start),
signature_at_call_stream.next_klass(), callee_signature_stream.next_klass());
if (exact != NULL) {
md->set_argument_type(bci, i, exact);
} }
} ciSignature* callee_signature = x->callee()->signature();
} else { // method handle call to virtual method
bool has_receiver = x->callee()->is_loaded() && !x->callee()->is_static() && !Bytecodes::has_receiver(bc);
ciSignatureStream callee_signature_stream(callee_signature, has_receiver ? x->callee()->holder() : NULL);
bool ignored_will_link;
ciSignature* signature_at_call = NULL;
x->method()->get_method_at_bci(bci, ignored_will_link, &signature_at_call);
ciSignatureStream signature_at_call_stream(signature_at_call);
// if called through method handle invoke, some arguments may have been popped
for (int i = 0; i < stop && i+start < x->nb_profiled_args(); i++) {
int off = in_bytes(TypeEntriesAtCall::argument_type_offset(i)) - in_bytes(TypeEntriesAtCall::args_data_offset());
ciKlass* exact = profile_type(md, base_offset, off,
args->type(i), x->profiled_arg_at(i+start), mdp,
!x->arg_needs_null_check(i+start),
signature_at_call_stream.next_klass(), callee_signature_stream.next_klass());
if (exact != NULL) {
md->set_argument_type(bci, i, exact);
}
}
} else {
#ifdef ASSERT #ifdef ASSERT
Bytecodes::Code code = x->method()->raw_code_at_bci(x->bci_of_invoke()); Bytecodes::Code code = x->method()->raw_code_at_bci(x->bci_of_invoke());
int n = x->nb_profiled_args(); int n = x->nb_profiled_args();
assert(MethodData::profile_parameters() && (MethodData::profile_arguments_jsr292_only() || assert(MethodData::profile_parameters() && (MethodData::profile_arguments_jsr292_only() ||
(x->inlined() && ((code == Bytecodes::_invokedynamic && n <= 1) || (code == Bytecodes::_invokehandle && n <= 2)))), (x->inlined() && ((code == Bytecodes::_invokedynamic && n <= 1) || (code == Bytecodes::_invokehandle && n <= 2)))),
"only at JSR292 bytecodes"); "only at JSR292 bytecodes");
#endif #endif
}
} }
} }
} }
...@@ -3319,24 +3321,26 @@ void LIRGenerator::do_ProfileReturnType(ProfileReturnType* x) { ...@@ -3319,24 +3321,26 @@ void LIRGenerator::do_ProfileReturnType(ProfileReturnType* x) {
int bci = x->bci_of_invoke(); int bci = x->bci_of_invoke();
ciMethodData* md = x->method()->method_data_or_null(); ciMethodData* md = x->method()->method_data_or_null();
ciProfileData* data = md->bci_to_data(bci); ciProfileData* data = md->bci_to_data(bci);
assert(data->is_CallTypeData() || data->is_VirtualCallTypeData(), "wrong profile data type"); if (data != NULL) {
ciReturnTypeEntry* ret = data->is_CallTypeData() ? ((ciCallTypeData*)data)->ret() : ((ciVirtualCallTypeData*)data)->ret(); assert(data->is_CallTypeData() || data->is_VirtualCallTypeData(), "wrong profile data type");
LIR_Opr mdp = LIR_OprFact::illegalOpr; ciReturnTypeEntry* ret = data->is_CallTypeData() ? ((ciCallTypeData*)data)->ret() : ((ciVirtualCallTypeData*)data)->ret();
LIR_Opr mdp = LIR_OprFact::illegalOpr;
bool ignored_will_link;
ciSignature* signature_at_call = NULL; bool ignored_will_link;
x->method()->get_method_at_bci(bci, ignored_will_link, &signature_at_call); ciSignature* signature_at_call = NULL;
x->method()->get_method_at_bci(bci, ignored_will_link, &signature_at_call);
// The offset within the MDO of the entry to update may be too large
// to be used in load/store instructions on some platforms. So have // The offset within the MDO of the entry to update may be too large
// profile_type() compute the address of the profile in a register. // to be used in load/store instructions on some platforms. So have
ciKlass* exact = profile_type(md, md->byte_offset_of_slot(data, ret->type_offset()), 0, // profile_type() compute the address of the profile in a register.
ret->type(), x->ret(), mdp, ciKlass* exact = profile_type(md, md->byte_offset_of_slot(data, ret->type_offset()), 0,
!x->needs_null_check(), ret->type(), x->ret(), mdp,
signature_at_call->return_type()->as_klass(), !x->needs_null_check(),
x->callee()->signature()->return_type()->as_klass()); signature_at_call->return_type()->as_klass(),
if (exact != NULL) { x->callee()->signature()->return_type()->as_klass());
md->set_return_type(bci, exact); if (exact != NULL) {
md->set_return_type(bci, exact);
}
} }
} }
......
...@@ -391,11 +391,13 @@ void ciMethodData::set_argument_type(int bci, int i, ciKlass* k) { ...@@ -391,11 +391,13 @@ void ciMethodData::set_argument_type(int bci, int i, ciKlass* k) {
MethodData* mdo = get_MethodData(); MethodData* mdo = get_MethodData();
if (mdo != NULL) { if (mdo != NULL) {
ProfileData* data = mdo->bci_to_data(bci); ProfileData* data = mdo->bci_to_data(bci);
if (data->is_CallTypeData()) { if (data != NULL) {
data->as_CallTypeData()->set_argument_type(i, k->get_Klass()); if (data->is_CallTypeData()) {
} else { data->as_CallTypeData()->set_argument_type(i, k->get_Klass());
assert(data->is_VirtualCallTypeData(), "no arguments!"); } else {
data->as_VirtualCallTypeData()->set_argument_type(i, k->get_Klass()); assert(data->is_VirtualCallTypeData(), "no arguments!");
data->as_VirtualCallTypeData()->set_argument_type(i, k->get_Klass());
}
} }
} }
} }
...@@ -413,11 +415,13 @@ void ciMethodData::set_return_type(int bci, ciKlass* k) { ...@@ -413,11 +415,13 @@ void ciMethodData::set_return_type(int bci, ciKlass* k) {
MethodData* mdo = get_MethodData(); MethodData* mdo = get_MethodData();
if (mdo != NULL) { if (mdo != NULL) {
ProfileData* data = mdo->bci_to_data(bci); ProfileData* data = mdo->bci_to_data(bci);
if (data->is_CallTypeData()) { if (data != NULL) {
data->as_CallTypeData()->set_return_type(k->get_Klass()); if (data->is_CallTypeData()) {
} else { data->as_CallTypeData()->set_return_type(k->get_Klass());
assert(data->is_VirtualCallTypeData(), "no arguments!"); } else {
data->as_VirtualCallTypeData()->set_return_type(k->get_Klass()); assert(data->is_VirtualCallTypeData(), "no arguments!");
data->as_VirtualCallTypeData()->set_return_type(k->get_Klass());
}
} }
} }
} }
......
...@@ -812,6 +812,9 @@ float Parse::dynamic_branch_prediction(float &cnt, BoolTest::mask btest, Node* t ...@@ -812,6 +812,9 @@ float Parse::dynamic_branch_prediction(float &cnt, BoolTest::mask btest, Node* t
ciMethodData* methodData = method()->method_data(); ciMethodData* methodData = method()->method_data();
if (!methodData->is_mature()) return PROB_UNKNOWN; if (!methodData->is_mature()) return PROB_UNKNOWN;
ciProfileData* data = methodData->bci_to_data(bci()); ciProfileData* data = methodData->bci_to_data(bci());
if (data == NULL) {
return PROB_UNKNOWN;
}
if (!data->is_JumpData()) return PROB_UNKNOWN; if (!data->is_JumpData()) return PROB_UNKNOWN;
// get taken and not taken values // get taken and not taken values
...@@ -903,8 +906,8 @@ float Parse::branch_prediction(float& cnt, ...@@ -903,8 +906,8 @@ float Parse::branch_prediction(float& cnt,
// of the OSR-ed method, and we want to deopt to gather more stats. // of the OSR-ed method, and we want to deopt to gather more stats.
// If you have ANY counts, then this loop is simply 'cold' relative // If you have ANY counts, then this loop is simply 'cold' relative
// to the OSR loop. // to the OSR loop.
if (data->as_BranchData()->taken() + if (data == NULL ||
data->as_BranchData()->not_taken() == 0 ) { (data->as_BranchData()->taken() + data->as_BranchData()->not_taken() == 0)) {
// This is the only way to return PROB_UNKNOWN: // This is the only way to return PROB_UNKNOWN:
return PROB_UNKNOWN; return PROB_UNKNOWN;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册