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
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Thu Mar 09 00:16:51 2017 -0800
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Thu Mar 09 14:27:21 2017 +0100
@@ -1540,7 +1540,7 @@
ciMethod* caller = state()->scope()->method();
ciMethodData* md = caller->method_data_or_null();
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();
// May not be true in case of an inlined call through a method handle intrinsic.
if (has_return) {
@@ -1758,7 +1758,7 @@
start = has_receiver ? 1 : 0;
if (profile_arguments()) {
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();
}
}
@@ -4349,7 +4349,7 @@
}
ciMethodData* md = m->method_data_or_null();
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));
}
}
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Thu Mar 09 00:16:51 2017 -0800
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Thu Mar 09 14:27:21 2017 +0100
@@ -3262,50 +3262,52 @@
int bci = x->bci_of_invoke();
ciMethodData* md = x->method()->method_data_or_null();
ciProfileData* data = md->bci_to_data(bci);
- if ((data->is_CallTypeData() && data->as_CallTypeData()->has_arguments()) ||
- (data->is_VirtualCallTypeData() && data->as_VirtualCallTypeData()->has_arguments())) {
- ByteSize extra = data->is_CallTypeData() ? CallTypeData::args_data_offset() : VirtualCallTypeData::args_data_offset();
- int base_offset = md->byte_offset_of_slot(data, extra);
- 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;
- int stop = data->is_CallTypeData() ? ((ciCallTypeData*)data)->number_of_arguments() : ((ciVirtualCallTypeData*)data)->number_of_arguments();
- if (x->callee()->is_loaded() && x->callee()->is_static() && Bytecodes::has_receiver(bc)) {
- // first argument is not profiled at call (method handle invoke)
- assert(x->method()->raw_code_at_bci(bci) == Bytecodes::_invokehandle, "invokehandle expected");
- start = 1;
+ if (data != NULL) {
+ if ((data->is_CallTypeData() && data->as_CallTypeData()->has_arguments()) ||
+ (data->is_VirtualCallTypeData() && data->as_VirtualCallTypeData()->has_arguments())) {
+ ByteSize extra = data->is_CallTypeData() ? CallTypeData::args_data_offset() : VirtualCallTypeData::args_data_offset();
+ int base_offset = md->byte_offset_of_slot(data, extra);
+ 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;
+ int stop = data->is_CallTypeData() ? ((ciCallTypeData*)data)->number_of_arguments() : ((ciVirtualCallTypeData*)data)->number_of_arguments();
+ if (x->callee()->is_loaded() && x->callee()->is_static() && Bytecodes::has_receiver(bc)) {
+ // first argument is not profiled at call (method handle invoke)
+ 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);
+ }
+ }
+ } else {
+#ifdef ASSERT
+ Bytecodes::Code code = x->method()->raw_code_at_bci(x->bci_of_invoke());
+ int n = x->nb_profiled_args();
+ assert(MethodData::profile_parameters() && (MethodData::profile_arguments_jsr292_only() ||
+ (x->inlined() && ((code == Bytecodes::_invokedynamic && n <= 1) || (code == Bytecodes::_invokehandle && n <= 2)))),
+ "only at JSR292 bytecodes");
+#endif
}
- 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);
- }
- }
- } else {
-#ifdef ASSERT
- Bytecodes::Code code = x->method()->raw_code_at_bci(x->bci_of_invoke());
- int n = x->nb_profiled_args();
- assert(MethodData::profile_parameters() && (MethodData::profile_arguments_jsr292_only() ||
- (x->inlined() && ((code == Bytecodes::_invokedynamic && n <= 1) || (code == Bytecodes::_invokehandle && n <= 2)))),
- "only at JSR292 bytecodes");
-#endif
}
}
}
@@ -3396,24 +3398,26 @@
int bci = x->bci_of_invoke();
ciMethodData* md = x->method()->method_data_or_null();
ciProfileData* data = md->bci_to_data(bci);
- assert(data->is_CallTypeData() || data->is_VirtualCallTypeData(), "wrong profile data type");
- 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;
- 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
- // profile_type() compute the address of the profile in a register.
- ciKlass* exact = profile_type(md, md->byte_offset_of_slot(data, ret->type_offset()), 0,
- ret->type(), x->ret(), mdp,
- !x->needs_null_check(),
- signature_at_call->return_type()->as_klass(),
- x->callee()->signature()->return_type()->as_klass());
- if (exact != NULL) {
- md->set_return_type(bci, exact);
+ if (data != NULL) {
+ assert(data->is_CallTypeData() || data->is_VirtualCallTypeData(), "wrong profile data type");
+ 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;
+ 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
+ // profile_type() compute the address of the profile in a register.
+ ciKlass* exact = profile_type(md, md->byte_offset_of_slot(data, ret->type_offset()), 0,
+ ret->type(), x->ret(), mdp,
+ !x->needs_null_check(),
+ signature_at_call->return_type()->as_klass(),
+ x->callee()->signature()->return_type()->as_klass());
+ if (exact != NULL) {
+ md->set_return_type(bci, exact);
+ }
}
}
--- a/hotspot/src/share/vm/ci/ciMethodData.cpp Thu Mar 09 00:16:51 2017 -0800
+++ b/hotspot/src/share/vm/ci/ciMethodData.cpp Thu Mar 09 14:27:21 2017 +0100
@@ -408,11 +408,13 @@
MethodData* mdo = get_MethodData();
if (mdo != NULL) {
ProfileData* data = mdo->bci_to_data(bci);
- if (data->is_CallTypeData()) {
- data->as_CallTypeData()->set_argument_type(i, k->get_Klass());
- } else {
- assert(data->is_VirtualCallTypeData(), "no arguments!");
- data->as_VirtualCallTypeData()->set_argument_type(i, k->get_Klass());
+ if (data != NULL) {
+ if (data->is_CallTypeData()) {
+ data->as_CallTypeData()->set_argument_type(i, k->get_Klass());
+ } else {
+ assert(data->is_VirtualCallTypeData(), "no arguments!");
+ data->as_VirtualCallTypeData()->set_argument_type(i, k->get_Klass());
+ }
}
}
}
@@ -430,11 +432,13 @@
MethodData* mdo = get_MethodData();
if (mdo != NULL) {
ProfileData* data = mdo->bci_to_data(bci);
- if (data->is_CallTypeData()) {
- data->as_CallTypeData()->set_return_type(k->get_Klass());
- } else {
- assert(data->is_VirtualCallTypeData(), "no arguments!");
- data->as_VirtualCallTypeData()->set_return_type(k->get_Klass());
+ if (data != NULL) {
+ if (data->is_CallTypeData()) {
+ data->as_CallTypeData()->set_return_type(k->get_Klass());
+ } else {
+ assert(data->is_VirtualCallTypeData(), "no arguments!");
+ data->as_VirtualCallTypeData()->set_return_type(k->get_Klass());
+ }
}
}
}
--- a/hotspot/src/share/vm/opto/parse2.cpp Thu Mar 09 00:16:51 2017 -0800
+++ b/hotspot/src/share/vm/opto/parse2.cpp Thu Mar 09 14:27:21 2017 +0100
@@ -826,6 +826,9 @@
ciMethodData* methodData = method()->method_data();
if (!methodData->is_mature()) return PROB_UNKNOWN;
ciProfileData* data = methodData->bci_to_data(bci());
+ if (data == NULL) {
+ return PROB_UNKNOWN;
+ }
if (!data->is_JumpData()) return PROB_UNKNOWN;
// get taken and not taken values
@@ -917,8 +920,8 @@
// 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
// to the OSR loop.
- if (data->as_BranchData()->taken() +
- data->as_BranchData()->not_taken() == 0 ) {
+ if (data == NULL ||
+ (data->as_BranchData()->taken() + data->as_BranchData()->not_taken() == 0)) {
// This is the only way to return PROB_UNKNOWN:
return PROB_UNKNOWN;
}