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 5411 : 8026251: New type profiling points: parameters to methods
Summary: x86 interpreter and c1 type profiling for parameters on method entries
Reviewed-by:
*** 39,49 ****
//
// Overlay for generic profiling data.
// Some types of data layouts need a length field.
bool DataLayout::needs_array_len(u1 tag) {
! return (tag == multi_branch_data_tag) || (tag == arg_info_data_tag);
}
// Perform generic initialization of the data. More specific
// initialization occurs in overrides of ProfileData::post_initialize.
void DataLayout::initialize(u1 tag, u2 bci, int cell_count) {
--- 39,49 ----
//
// Overlay for generic profiling data.
// Some types of data layouts need a length field.
bool DataLayout::needs_array_len(u1 tag) {
! return (tag == multi_branch_data_tag) || (tag == arg_info_data_tag) || (tag == parameters_type_data_tag);
}
// Perform generic initialization of the data. More specific
// initialization occurs in overrides of ProfileData::post_initialize.
void DataLayout::initialize(u1 tag, u2 bci, int cell_count) {
*** 154,177 ****
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();
}
--- 154,179 ----
print_shared(st, "JumpData");
st->print_cr("taken(%u) displacement(%d)", taken(), displacement());
}
#endif // !PRODUCT
! int TypeStackSlotEntries::compute_cell_count(Symbol* signature, bool include_receiver, int max) {
! int args_count = include_receiver ? 1 : 0;
ResourceMark rm;
SignatureStream ss(signature);
! args_count += ss.reference_parameter_count();
! args_count = MIN2(args_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(), false, 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();
}
*** 210,225 ****
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) {
--- 212,233 ----
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, bool include_receiver) {
ResourceMark rm;
! int start = 0;
! if (include_receiver && has_receiver) {
! set_stack_slot(0, 0);
! set_type(0, type_none());
! start += 1;
! }
! ArgumentOffsetComputer aos(signature, _number_of_entries-start);
aos.total();
! for (int i = start; i < _number_of_entries; i++) {
! set_stack_slot(i, aos.off_at(i-start) + (has_receiver ? 1 : 0));
set_type(i, type_none());
}
}
void CallTypeData::post_initialize(BytecodeStream* stream, MethodData* mdo) {
*** 232,242 ****
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();
--- 240,250 ----
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(), false);
}
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();
*** 253,263 ****
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();
--- 261,271 ----
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(), false);
}
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();
*** 577,586 ****
--- 585,622 ----
}
st->cr();
}
#endif
+
+ int ParametersTypeData::compute_cell_count(Method* m) {
+ if (!MethodData::profile_parameters_for_method(m)) {
+ return 0;
+ }
+ int max = TypeProfileParmsLimit == -1 ? INT_MAX : TypeProfileParmsLimit;
+ int obj_args = TypeStackSlotEntries::compute_cell_count(m->signature(), !m->is_static(), max);
+ if (obj_args > 0) {
+ return obj_args + 1; // 1 cell for array len
+ }
+ return 0;
+ }
+
+ void ParametersTypeData::post_initialize(BytecodeStream* stream, MethodData* mdo) {
+ _parameters.post_initialize(mdo->method()->signature(), !mdo->method()->is_static(), true);
+ }
+
+ bool ParametersTypeData::profiling_enabled() {
+ return MethodData::profile_parameters();
+ }
+
+ #ifndef PRODUCT
+ void ParametersTypeData::print_data_on(outputStream* st) const {
+ st->print("parameter types");
+ _parameters.print_data_on(st);
+ }
+ #endif
+
// ==================================================================
// MethodData*
//
// A MethodData* holds information which has been collected about
// a method.
*** 739,748 ****
--- 775,788 ----
// Add a cell to record information about modified arguments.
int arg_size = method->size_of_parameters();
object_size += DataLayout::compute_size_in_bytes(arg_size+1);
+ int args_cell = ParametersTypeData::compute_cell_count(method());
+ if (args_cell > 0) {
+ object_size += DataLayout::compute_size_in_bytes(args_cell);
+ }
return object_size;
}
// Compute the size of the MethodData* necessary to store
// profiling information about a given method. Size is in words
*** 913,922 ****
--- 953,964 ----
return new ArgInfoData(this);
case DataLayout::call_type_data_tag:
return new CallTypeData(this);
case DataLayout::virtual_call_type_data_tag:
return new VirtualCallTypeData(this);
+ case DataLayout::parameters_type_data_tag:
+ return new ParametersTypeData(this);
};
}
// Iteration over data.
ProfileData* MethodData::next_data(ProfileData* current) const {
*** 934,943 ****
--- 976,988 ----
for (data = first_data(); is_valid(data); data = next_data(data)) {
stream->set_start(data->bci());
stream->next();
data->post_initialize(stream, this);
}
+ if (_parameters_type_data_di != -1) {
+ parameters_type_data()->post_initialize(NULL, this);
+ }
}
// Initialize the MethodData* corresponding to a given method.
MethodData::MethodData(methodHandle method, int size, TRAPS) {
No_Safepoint_Verifier no_safepoint; // init function atomic wrt GC
*** 973,983 ****
DataLayout *dp = data_layout_at(data_size + extra_size);
int arg_size = method->size_of_parameters();
dp->initialize(DataLayout::arg_info_data_tag, 0, arg_size+1);
! object_size += extra_size + DataLayout::compute_size_in_bytes(arg_size+1);
// Set an initial hint. Don't use set_hint_di() because
// first_di() may be out of bounds if data_size is 0.
// In that situation, _hint_di is never used, but at
// least well-defined.
--- 1018,1039 ----
DataLayout *dp = data_layout_at(data_size + extra_size);
int arg_size = method->size_of_parameters();
dp->initialize(DataLayout::arg_info_data_tag, 0, arg_size+1);
! int arg_data_size = DataLayout::compute_size_in_bytes(arg_size+1);
! object_size += extra_size + arg_data_size;
!
! int args_cell = ParametersTypeData::compute_cell_count(method());
! if (args_cell > 0) {
! object_size += DataLayout::compute_size_in_bytes(args_cell);
! _parameters_type_data_di = data_size + extra_size + arg_data_size;
! DataLayout *dp = data_layout_at(data_size + extra_size + arg_data_size);
! dp->initialize(DataLayout::parameters_type_data_tag, 0, args_cell);
! } else {
! _parameters_type_data_di = -1;
! }
// Set an initial hint. Don't use set_hint_di() because
// first_di() may be out of bounds if data_size is 0.
// In that situation, _hint_di is never used, but at
// least well-defined.
*** 1132,1141 ****
--- 1188,1200 ----
#ifndef PRODUCT
void MethodData::print_data_on(outputStream* st) const {
ResourceMark rm;
ProfileData* data = first_data();
+ if (_parameters_type_data_di != -1) {
+ parameters_type_data()->print_data_on(st);
+ }
for ( ; is_valid(data); data = next_data(data)) {
st->print("%d", dp_to_di(data->dp()));
st->fill_to(6);
data->print_data_on(st);
}
*** 1220,1230 ****
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;
}
--- 1279,1289 ----
assert(profile_arguments_jsr292_only(), "inconsistent");
return profile_jsr292(m, bci);
}
int MethodData::profile_return_flag() {
! return (TypeProfileLevel % 100) / 10;
}
bool MethodData::profile_return() {
return profile_return_flag() > no_type_profile && profile_return_flag() <= type_profile_all;
}
*** 1247,1251 ****
--- 1306,1339 ----
}
assert(profile_return_jsr292_only(), "inconsistent");
return profile_jsr292(m, bci);
}
+
+ int MethodData::profile_parameters_flag() {
+ return TypeProfileLevel / 100;
+ }
+
+ bool MethodData::profile_parameters() {
+ return profile_parameters_flag() > no_type_profile && profile_parameters_flag() <= type_profile_all;
+ }
+
+ bool MethodData::profile_parameters_jsr292_only() {
+ return profile_parameters_flag() == type_profile_jsr292;
+ }
+
+ bool MethodData::profile_all_parameters() {
+ return profile_parameters_flag() == type_profile_all;
+ }
+
+ bool MethodData::profile_parameters_for_method(methodHandle m) {
+ if (!profile_parameters()) {
+ return false;
+ }
+
+ if (profile_all_parameters()) {
+ return true;
+ }
+
+ assert(profile_parameters_jsr292_only(), "inconsistent");
+ return m->is_compiled_lambda_form();
+ }
src/share/vm/oops/methodData.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File