src/share/vm/oops/methodData.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File
hotspot Cdiff src/share/vm/oops/methodData.cpp
src/share/vm/oops/methodData.cpp
Print this page
rev 5403 : 8023657: New type profiling points: arguments to call
Summary: x86 interpreter and c1 type profiling for arguments at calls
Reviewed-by: kvn, twisti
rev 5404 : 8026054: New type profiling points: type of return values at calls
Summary: x86 interpreter and c1 type profiling for return values at calls
Reviewed-by:
rev 5405 : imported patch kvn
rev 5406 : imported patch twisti
rev 5407 : imported patch fixreturn
*** 154,173 ****
print_shared(st, "JumpData");
st->print_cr("taken(%u) displacement(%d)", taken(), displacement());
}
#endif // !PRODUCT
! int TypeStackSlotEntries::compute_cell_count(BytecodeStream* stream) {
! int max = TypeProfileArgsLimit;
! assert(Bytecodes::is_invoke(stream->code()), "should be invoke");
! Bytecode_invoke inv(stream->method(), stream->bci());
!
ResourceMark rm;
! SignatureStream ss(inv.signature());
int args_count = MIN2(ss.reference_parameter_count(), max);
! return args_count * per_arg_cell_count + (args_count > 0 ? header_cell_count() : 0);
}
class ArgumentOffsetComputer : public SignatureInfo {
private:
int _max;
--- 154,188 ----
print_shared(st, "JumpData");
st->print_cr("taken(%u) displacement(%d)", taken(), displacement());
}
#endif // !PRODUCT
! int TypeStackSlotEntries::compute_cell_count(Symbol* signature, int max) {
ResourceMark rm;
! SignatureStream ss(signature);
int args_count = MIN2(ss.reference_parameter_count(), max);
+ return args_count * per_arg_cell_count;
+ }
! int TypeEntriesAtCall::compute_cell_count(BytecodeStream* stream) {
! assert(Bytecodes::is_invoke(stream->code()), "should be invoke");
! assert(TypeStackSlotEntries::per_arg_count() > ReturnTypeEntry::static_cell_count(), "code to test for arguments/results broken");
! Bytecode_invoke inv(stream->method(), stream->bci());
! int args_cell = 0;
! if (arguments_profiling_enabled()) {
! args_cell = TypeStackSlotEntries::compute_cell_count(inv.signature(), TypeProfileArgsLimit);
! }
! int ret_cell = 0;
! if (return_profiling_enabled() && (inv.result_type() == T_OBJECT || inv.result_type() == T_ARRAY)) {
! ret_cell = ReturnTypeEntry::static_cell_count();
! }
! int header_cell = 0;
! if (args_cell + ret_cell > 0) {
! header_cell = header_cell_count();
! }
!
! return header_cell + args_cell + ret_cell;
}
class ArgumentOffsetComputer : public SignatureInfo {
private:
int _max;
*** 195,242 ****
int total() { lazy_iterate_parameters(); return _size; }
int off_at(int i) const { return _offsets.at(i); }
};
! void TypeStackSlotEntries::post_initialize(BytecodeStream* stream) {
ResourceMark rm;
assert(Bytecodes::is_invoke(stream->code()), "should be invoke");
Bytecode_invoke inv(stream->method(), stream->bci());
#ifdef ASSERT
SignatureStream ss(inv.signature());
int count = MIN2(ss.reference_parameter_count(), (int)TypeProfileArgsLimit);
assert(count > 0, "room for args type but none found?");
check_number_of_arguments(count);
#endif
! int start = 0;
! ArgumentOffsetComputer aos(inv.signature(), number_of_arguments()-start);
! aos.total();
! bool has_receiver = inv.has_receiver();
! for (int i = start; i < number_of_arguments(); i++) {
! set_stack_slot(i, aos.off_at(i-start) + (has_receiver ? 1 : 0));
! set_type(i, type_none());
}
}
bool TypeEntries::is_loader_alive(BoolObjectClosure* is_alive_cl, intptr_t p) {
return !is_type_none(p) &&
!((Klass*)klass_part(p))->is_loader_alive(is_alive_cl);
}
void TypeStackSlotEntries::clean_weak_klass_links(BoolObjectClosure* is_alive_cl) {
! for (int i = 0; i < number_of_arguments(); i++) {
intptr_t p = type(i);
if (is_loader_alive(is_alive_cl, p)) {
set_type(i, type_none());
}
}
}
! bool TypeStackSlotEntries::arguments_profiling_enabled() {
return MethodData::profile_arguments();
}
#ifndef PRODUCT
void TypeEntries::print_klass(outputStream* st, intptr_t k) {
--- 210,297 ----
int total() { lazy_iterate_parameters(); return _size; }
int off_at(int i) const { return _offsets.at(i); }
};
! void TypeStackSlotEntries::post_initialize(Symbol* signature, bool has_receiver) {
! ResourceMark rm;
! ArgumentOffsetComputer aos(signature, _number_of_entries);
! aos.total();
! for (int i = 0; i < _number_of_entries; i++) {
! set_stack_slot(i, aos.off_at(i) + (has_receiver ? 1 : 0));
! set_type(i, type_none());
! }
! }
!
! void CallTypeData::post_initialize(BytecodeStream* stream, MethodData* mdo) {
! assert(Bytecodes::is_invoke(stream->code()), "should be invoke");
! Bytecode_invoke inv(stream->method(), stream->bci());
!
! SignatureStream ss(inv.signature());
! if (has_arguments()) {
! #ifdef ASSERT
ResourceMark rm;
+ int count = MIN2(ss.reference_parameter_count(), (int)TypeProfileArgsLimit);
+ assert(count > 0, "room for args type but none found?");
+ check_number_of_arguments(count);
+ #endif
+ _args.post_initialize(inv.signature(), inv.has_receiver());
+ }
+
+ if (has_return()) {
+ assert(inv.result_type() == T_OBJECT || inv.result_type() == T_ARRAY, "room for a ret type but doesn't return obj?");
+ _ret.post_initialize();
+ }
+ }
+ void VirtualCallTypeData::post_initialize(BytecodeStream* stream, MethodData* mdo) {
assert(Bytecodes::is_invoke(stream->code()), "should be invoke");
Bytecode_invoke inv(stream->method(), stream->bci());
+ if (has_arguments()) {
#ifdef ASSERT
+ ResourceMark rm;
SignatureStream ss(inv.signature());
int count = MIN2(ss.reference_parameter_count(), (int)TypeProfileArgsLimit);
assert(count > 0, "room for args type but none found?");
check_number_of_arguments(count);
#endif
+ _args.post_initialize(inv.signature(), inv.has_receiver());
+ }
! if (has_return()) {
! assert(inv.result_type() == T_OBJECT || inv.result_type() == T_ARRAY, "room for a ret type but doesn't return obj?");
! _ret.post_initialize();
}
}
bool TypeEntries::is_loader_alive(BoolObjectClosure* is_alive_cl, intptr_t p) {
return !is_type_none(p) &&
!((Klass*)klass_part(p))->is_loader_alive(is_alive_cl);
}
void TypeStackSlotEntries::clean_weak_klass_links(BoolObjectClosure* is_alive_cl) {
! for (int i = 0; i < _number_of_entries; i++) {
intptr_t p = type(i);
if (is_loader_alive(is_alive_cl, p)) {
set_type(i, type_none());
}
}
}
! void ReturnTypeEntry::clean_weak_klass_links(BoolObjectClosure* is_alive_cl) {
! intptr_t p = type();
! if (is_loader_alive(is_alive_cl, p)) {
! set_type(type_none());
! }
! }
!
! bool TypeEntriesAtCall::return_profiling_enabled() {
! return MethodData::profile_return();
! }
!
! bool TypeEntriesAtCall::arguments_profiling_enabled() {
return MethodData::profile_arguments();
}
#ifndef PRODUCT
void TypeEntries::print_klass(outputStream* st, intptr_t k) {
*** 251,278 ****
st->print(" (null seen)");
}
}
void TypeStackSlotEntries::print_data_on(outputStream* st) const {
! _pd->tab(st, true);
! st->print("argument types");
! for (int i = 0; i < number_of_arguments(); i++) {
_pd->tab(st);
st->print("%d: stack(%u) ", i, stack_slot(i));
print_klass(st, type(i));
st->cr();
}
}
void CallTypeData::print_data_on(outputStream* st) const {
CounterData::print_data_on(st);
_args.print_data_on(st);
}
void VirtualCallTypeData::print_data_on(outputStream* st) const {
VirtualCallData::print_data_on(st);
_args.print_data_on(st);
}
#endif
// ==================================================================
// ReceiverTypeData
--- 306,355 ----
st->print(" (null seen)");
}
}
void TypeStackSlotEntries::print_data_on(outputStream* st) const {
! for (int i = 0; i < _number_of_entries; i++) {
_pd->tab(st);
st->print("%d: stack(%u) ", i, stack_slot(i));
print_klass(st, type(i));
st->cr();
}
}
+ void ReturnTypeEntry::print_data_on(outputStream* st) const {
+ _pd->tab(st);
+ print_klass(st, type());
+ st->cr();
+ }
+
void CallTypeData::print_data_on(outputStream* st) const {
CounterData::print_data_on(st);
+ if (has_arguments()) {
+ tab(st, true);
+ st->print("argument types");
_args.print_data_on(st);
+ }
+ if (has_return()) {
+ tab(st, true);
+ st->print("return type");
+ _ret.print_data_on(st);
+ }
}
void VirtualCallTypeData::print_data_on(outputStream* st) const {
VirtualCallData::print_data_on(st);
+ if (has_arguments()) {
+ tab(st, true);
+ st->print("argument types");
_args.print_data_on(st);
+ }
+ if (has_return()) {
+ tab(st, true);
+ st->print("return type");
+ _ret.print_data_on(st);
+ }
}
#endif
// ==================================================================
// ReceiverTypeData
*** 528,538 ****
} else {
return BitData::static_cell_count();
}
case Bytecodes::_invokespecial:
case Bytecodes::_invokestatic:
! if (MethodData::profile_arguments()) {
return variable_cell_count;
} else {
return CounterData::static_cell_count();
}
case Bytecodes::_goto:
--- 605,615 ----
} else {
return BitData::static_cell_count();
}
case Bytecodes::_invokespecial:
case Bytecodes::_invokestatic:
! if (MethodData::profile_arguments() || MethodData::profile_return()) {
return variable_cell_count;
} else {
return CounterData::static_cell_count();
}
case Bytecodes::_goto:
*** 540,556 ****
case Bytecodes::_jsr:
case Bytecodes::_jsr_w:
return JumpData::static_cell_count();
case Bytecodes::_invokevirtual:
case Bytecodes::_invokeinterface:
! if (MethodData::profile_arguments()) {
return variable_cell_count;
} else {
return VirtualCallData::static_cell_count();
}
case Bytecodes::_invokedynamic:
! if (MethodData::profile_arguments()) {
return variable_cell_count;
} else {
return CounterData::static_cell_count();
}
case Bytecodes::_ret:
--- 617,633 ----
case Bytecodes::_jsr:
case Bytecodes::_jsr_w:
return JumpData::static_cell_count();
case Bytecodes::_invokevirtual:
case Bytecodes::_invokeinterface:
! if (MethodData::profile_arguments() || MethodData::profile_return()) {
return variable_cell_count;
} else {
return VirtualCallData::static_cell_count();
}
case Bytecodes::_invokedynamic:
! if (MethodData::profile_arguments() || MethodData::profile_return()) {
return variable_cell_count;
} else {
return CounterData::static_cell_count();
}
case Bytecodes::_ret:
*** 594,614 ****
cell_count = MultiBranchData::compute_cell_count(stream);
break;
case Bytecodes::_invokespecial:
case Bytecodes::_invokestatic:
case Bytecodes::_invokedynamic:
! assert(MethodData::profile_arguments(), "should be collecting args profile");
! if (profile_arguments_for_invoke(stream->method(), stream->bci())) {
cell_count = CallTypeData::compute_cell_count(stream);
} else {
cell_count = CounterData::static_cell_count();
}
break;
case Bytecodes::_invokevirtual:
case Bytecodes::_invokeinterface: {
! assert(MethodData::profile_arguments(), "should be collecting args profile");
! if (profile_arguments_for_invoke(stream->method(), stream->bci())) {
cell_count = VirtualCallTypeData::compute_cell_count(stream);
} else {
cell_count = VirtualCallData::static_cell_count();
}
break;
--- 671,693 ----
cell_count = MultiBranchData::compute_cell_count(stream);
break;
case Bytecodes::_invokespecial:
case Bytecodes::_invokestatic:
case Bytecodes::_invokedynamic:
! assert(MethodData::profile_arguments() || MethodData::profile_return(), "should be collecting args profile");
! if (profile_arguments_for_invoke(stream->method(), stream->bci()) ||
! profile_return_for_invoke(stream->method(), stream->bci())) {
cell_count = CallTypeData::compute_cell_count(stream);
} else {
cell_count = CounterData::static_cell_count();
}
break;
case Bytecodes::_invokevirtual:
case Bytecodes::_invokeinterface: {
! assert(MethodData::profile_arguments() || MethodData::profile_return(), "should be collecting args profile");
! if (profile_arguments_for_invoke(stream->method(), stream->bci()) ||
! profile_return_for_invoke(stream->method(), stream->bci())) {
cell_count = VirtualCallTypeData::compute_cell_count(stream);
} else {
cell_count = VirtualCallData::static_cell_count();
}
break;
*** 697,707 ****
}
break;
case Bytecodes::_invokespecial:
case Bytecodes::_invokestatic: {
int counter_data_cell_count = CounterData::static_cell_count();
! if (profile_arguments_for_invoke(stream->method(), stream->bci())) {
cell_count = CallTypeData::compute_cell_count(stream);
} else {
cell_count = counter_data_cell_count;
}
if (cell_count > counter_data_cell_count) {
--- 776,787 ----
}
break;
case Bytecodes::_invokespecial:
case Bytecodes::_invokestatic: {
int counter_data_cell_count = CounterData::static_cell_count();
! if (profile_arguments_for_invoke(stream->method(), stream->bci()) ||
! profile_return_for_invoke(stream->method(), stream->bci())) {
cell_count = CallTypeData::compute_cell_count(stream);
} else {
cell_count = counter_data_cell_count;
}
if (cell_count > counter_data_cell_count) {
*** 719,729 ****
tag = DataLayout::jump_data_tag;
break;
case Bytecodes::_invokevirtual:
case Bytecodes::_invokeinterface: {
int virtual_call_data_cell_count = VirtualCallData::static_cell_count();
! if (profile_arguments_for_invoke(stream->method(), stream->bci())) {
cell_count = VirtualCallTypeData::compute_cell_count(stream);
} else {
cell_count = virtual_call_data_cell_count;
}
if (cell_count > virtual_call_data_cell_count) {
--- 799,810 ----
tag = DataLayout::jump_data_tag;
break;
case Bytecodes::_invokevirtual:
case Bytecodes::_invokeinterface: {
int virtual_call_data_cell_count = VirtualCallData::static_cell_count();
! if (profile_arguments_for_invoke(stream->method(), stream->bci()) ||
! profile_return_for_invoke(stream->method(), stream->bci())) {
cell_count = VirtualCallTypeData::compute_cell_count(stream);
} else {
cell_count = virtual_call_data_cell_count;
}
if (cell_count > virtual_call_data_cell_count) {
*** 734,744 ****
break;
}
case Bytecodes::_invokedynamic: {
// %%% should make a type profile for any invokedynamic that takes a ref argument
int counter_data_cell_count = CounterData::static_cell_count();
! if (profile_arguments_for_invoke(stream->method(), stream->bci())) {
cell_count = CallTypeData::compute_cell_count(stream);
} else {
cell_count = counter_data_cell_count;
}
if (cell_count > counter_data_cell_count) {
--- 815,826 ----
break;
}
case Bytecodes::_invokedynamic: {
// %%% should make a type profile for any invokedynamic that takes a ref argument
int counter_data_cell_count = CounterData::static_cell_count();
! if (profile_arguments_for_invoke(stream->method(), stream->bci()) ||
! profile_return_for_invoke(stream->method(), stream->bci())) {
cell_count = CallTypeData::compute_cell_count(stream);
} else {
cell_count = counter_data_cell_count;
}
if (cell_count > counter_data_cell_count) {
*** 776,786 ****
cell_count = MultiBranchData::compute_cell_count(stream);
tag = DataLayout::multi_branch_data_tag;
break;
}
assert(tag == DataLayout::multi_branch_data_tag ||
! (MethodData::profile_arguments() &&
(tag == DataLayout::call_type_data_tag ||
tag == DataLayout::counter_data_tag ||
tag == DataLayout::virtual_call_type_data_tag ||
tag == DataLayout::virtual_call_data_tag)) ||
cell_count == bytecode_cell_count(c), "cell counts must agree");
--- 858,868 ----
cell_count = MultiBranchData::compute_cell_count(stream);
tag = DataLayout::multi_branch_data_tag;
break;
}
assert(tag == DataLayout::multi_branch_data_tag ||
! ((MethodData::profile_arguments() || MethodData::profile_return()) &&
(tag == DataLayout::call_type_data_tag ||
tag == DataLayout::counter_data_tag ||
tag == DataLayout::virtual_call_type_data_tag ||
tag == DataLayout::virtual_call_data_tag)) ||
cell_count == bytecode_cell_count(c), "cell counts must agree");
*** 1109,1119 ****
Bytecode_invoke inv(m , bci);
return inv.is_invokedynamic() || inv.is_invokehandle();
}
int MethodData::profile_arguments_flag() {
! return TypeProfileLevel;
}
bool MethodData::profile_arguments() {
return profile_arguments_flag() > no_type_profile && profile_arguments_flag() <= type_profile_all;
}
--- 1191,1201 ----
Bytecode_invoke inv(m , bci);
return inv.is_invokedynamic() || inv.is_invokehandle();
}
int MethodData::profile_arguments_flag() {
! return TypeProfileLevel % 10;
}
bool MethodData::profile_arguments() {
return profile_arguments_flag() > no_type_profile && profile_arguments_flag() <= type_profile_all;
}
*** 1137,1141 ****
--- 1219,1251 ----
assert(profile_arguments_jsr292_only(), "inconsistent");
return profile_jsr292(m, bci);
}
+ int MethodData::profile_return_flag() {
+ return TypeProfileLevel / 10;
+ }
+
+ bool MethodData::profile_return() {
+ return profile_return_flag() > no_type_profile && profile_return_flag() <= type_profile_all;
+ }
+
+ bool MethodData::profile_return_jsr292_only() {
+ return profile_return_flag() == type_profile_jsr292;
+ }
+
+ bool MethodData::profile_all_return() {
+ return profile_return_flag() == type_profile_all;
+ }
+
+ bool MethodData::profile_return_for_invoke(methodHandle m, int bci) {
+ if (!profile_return()) {
+ return false;
+ }
+
+ if (profile_all_return()) {
+ return true;
+ }
+
+ assert(profile_return_jsr292_only(), "inconsistent");
+ return profile_jsr292(m, bci);
+ }
src/share/vm/oops/methodData.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File