src/share/vm/oops/methodData.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File
*** old/src/share/vm/oops/methodData.cpp Tue Oct 8 14:00:26 2013
--- new/src/share/vm/oops/methodData.cpp Tue Oct 8 14:00:26 2013
*** 54,63 ****
--- 54,68 ----
set_cell_at(i, (intptr_t)0);
}
if (needs_array_len(tag)) {
set_cell_at(ArrayData::array_len_off_set, cell_count - 1); // -1 for header.
}
+ if (tag == call_type_data_tag) {
+ CallTypeData::initialize(this, cell_count);
+ } else if (tag == virtual_call_type_data_tag) {
+ VirtualCallTypeData::initialize(this, cell_count);
+ }
}
void DataLayout::clean_weak_klass_links(BoolObjectClosure* cl) {
ResourceMark m;
data_in()->clean_weak_klass_links(cl);
*** 74,84 ****
--- 79,89 ----
ProfileData::ProfileData() {
_data = NULL;
}
#ifndef PRODUCT
! void ProfileData::print_shared(outputStream* st, const char* name) const {
st->print("bci: %d", bci());
st->fill_to(tab_width_one);
st->print("%s", name);
tab(st);
int trap = trap_state();
*** 89,100 ****
--- 94,105 ----
int flags = data()->flags();
if (flags != 0)
st->print("flags(%d) ", flags);
}
! void ProfileData::tab(outputStream* st, bool first) const {
! st->fill_to(tab_width_two);
! st->fill_to(first ? tab_width_one : tab_width_two);
}
#endif // !PRODUCT
// ==================================================================
// BitData
*** 102,123 ****
--- 107,128 ----
// A BitData corresponds to a one-bit flag. This is used to indicate
// whether a checkcast bytecode has seen a null value.
#ifndef PRODUCT
! void BitData::print_data_on(outputStream* st) const {
print_shared(st, "BitData");
}
#endif // !PRODUCT
// ==================================================================
// CounterData
//
// A CounterData corresponds to a simple counter.
#ifndef PRODUCT
! void CounterData::print_data_on(outputStream* st) const {
print_shared(st, "CounterData");
st->print_cr("count(%u)", count());
}
#endif // !PRODUCT
*** 143,158 ****
--- 148,281 ----
int offset = target_di - my_di;
set_displacement(offset);
}
#ifndef PRODUCT
! void JumpData::print_data_on(outputStream* st) const {
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;
+ GrowableArray<int> _offsets;
+
+ void set(int size, BasicType type) { _size += size; }
+ void do_object(int begin, int end) {
+ if (_offsets.length() < _max) {
+ _offsets.push(_size);
+ }
+ SignatureInfo::do_object(begin, end);
+ }
+ void do_array (int begin, int end) {
+ if (_offsets.length() < _max) {
+ _offsets.push(_size);
+ }
+ SignatureInfo::do_array(begin, end);
+ }
+
+ public:
+ ArgumentOffsetComputer(Symbol* signature, int max)
+ : SignatureInfo(signature), _max(max), _offsets(Thread::current(), max) {
+ }
+
+ 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(), 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) {
+ if (is_type_none(k)) {
+ st->print("none");
+ } else if (is_type_unknown(k)) {
+ st->print("unknown");
+ } else {
+ valid_klass(k)->print_value_on(st);
+ }
+ if (was_null_seen(k)) {
+ 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
//
// A ReceiverTypeData is used to access profiling information about a
// dynamic type check. It consists of a counter which counts the total times
*** 167,177 ****
--- 290,300 ----
}
}
}
#ifndef PRODUCT
! void ReceiverTypeData::print_receiver_data_on(outputStream* st) const {
uint row;
int entries = 0;
for (row = 0; row < row_limit(); row++) {
if (receiver(row) != NULL) entries++;
}
*** 188,202 ****
--- 311,325 ----
receiver(row)->print_value_on(st);
st->print_cr("(%u %4.2f)", receiver_count(row), (float) receiver_count(row) / (float) total);
}
}
}
! void ReceiverTypeData::print_data_on(outputStream* st) const {
print_shared(st, "ReceiverTypeData");
print_receiver_data_on(st);
}
! void VirtualCallData::print_data_on(outputStream* st) const {
print_shared(st, "VirtualCallData");
print_receiver_data_on(st);
}
#endif // !PRODUCT
*** 244,254 ****
--- 367,377 ----
return mdp;
}
#ifndef PRODUCT
! void RetData::print_data_on(outputStream* st) const {
print_shared(st, "RetData");
uint row;
int entries = 0;
for (row = 0; row < row_limit(); row++) {
if (bci(row) != no_bci) entries++;
*** 279,289 ****
--- 402,412 ----
int offset = target_di - my_di;
set_displacement(offset);
}
#ifndef PRODUCT
! void BranchData::print_data_on(outputStream* st) const {
print_shared(st, "BranchData");
st->print_cr("taken(%u) displacement(%d)",
taken(), displacement());
tab(st);
st->print_cr("not taken(%u)", not_taken());
*** 353,363 ****
--- 476,486 ----
set_default_displacement(offset);
}
}
#ifndef PRODUCT
! void MultiBranchData::print_data_on(outputStream* st) const {
print_shared(st, "MultiBranchData");
st->print_cr("default_count(%u) displacement(%d)",
default_count(), default_displacement());
int cases = number_of_cases();
for (int i = 0; i < cases; i++) {
*** 367,377 ****
--- 490,500 ----
}
}
#endif
#ifndef PRODUCT
! void ArgInfoData::print_data_on(outputStream* st) const {
print_shared(st, "ArgInfoData");
int nargs = number_of_args();
for (int i = 0; i < nargs; i++) {
st->print(" 0x%x", arg_modified(i));
}
*** 405,425 ****
--- 528,560 ----
} 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:
case Bytecodes::_goto_w:
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:
return RetData::static_cell_count();
case Bytecodes::_ifeq:
case Bytecodes::_ifne:
case Bytecodes::_iflt:
*** 451,461 ****
--- 586,623 ----
int cell_count = bytecode_cell_count(stream->code());
if (cell_count == no_profile_data) {
return 0;
}
if (cell_count == variable_cell_count) {
+ switch (stream->code()) {
+ case Bytecodes::_lookupswitch:
+ case Bytecodes::_tableswitch:
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;
+ }
+ default:
+ fatal("unexpected bytecode for var length profile data");
+ }
}
// Note: cell_count might be zero, meaning that there is just
// a DataLayout header, with no extra cells.
assert(cell_count >= 0, "sanity");
return DataLayout::compute_size_in_bytes(cell_count);
*** 497,506 ****
--- 659,669 ----
object_size += extra_data_count * DataLayout::compute_size_in_bytes(0);
// 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);
+
return object_size;
}
// Compute the size of the MethodData* necessary to store
// profiling information about a given method. Size is in words
*** 532,562 ****
--- 695,755 ----
cell_count = BitData::static_cell_count();
tag = DataLayout::bit_data_tag;
}
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) {
+ tag = DataLayout::call_type_data_tag;
+ } else {
tag = DataLayout::counter_data_tag;
+ }
break;
+ }
case Bytecodes::_goto:
case Bytecodes::_goto_w:
case Bytecodes::_jsr:
case Bytecodes::_jsr_w:
cell_count = JumpData::static_cell_count();
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) {
+ tag = DataLayout::virtual_call_type_data_tag;
+ } else {
tag = DataLayout::virtual_call_data_tag;
+ }
break;
case Bytecodes::_invokedynamic:
+ }
+ 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) {
+ tag = DataLayout::call_type_data_tag;
+ } else {
tag = DataLayout::counter_data_tag;
+ }
break;
+ }
case Bytecodes::_ret:
cell_count = RetData::static_cell_count();
tag = DataLayout::ret_data_tag;
break;
case Bytecodes::_ifeq:
*** 583,592 ****
--- 776,790 ----
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");
if (cell_count >= 0) {
assert(tag != DataLayout::no_tag, "bad tag");
assert(bytecode_has_profile(c), "agree w/ BHP");
data_layout->initialize(tag, stream->bci(), cell_count);
*** 629,638 ****
--- 827,840 ----
return new BranchData(this);
case DataLayout::multi_branch_data_tag:
return new MultiBranchData(this);
case DataLayout::arg_info_data_tag:
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);
};
}
// Iteration over data.
ProfileData* MethodData::next_data(ProfileData* current) const {
*** 896,900 ****
--- 1098,1141 ----
void MethodData::verify_data_on(outputStream* st) {
NEEDS_CLEANUP;
// not yet implemented.
}
+
+ bool MethodData::profile_jsr292(methodHandle m, int bci) {
+ if (m->is_compiled_lambda_form()) {
+ return true;
+ }
+
+ 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;
+ }
+
+ bool MethodData::profile_arguments_jsr292_only() {
+ return profile_arguments_flag() == type_profile_jsr292;
+ }
+
+ bool MethodData::profile_all_arguments() {
+ return profile_arguments_flag() == type_profile_all;
+ }
+
+ bool MethodData::profile_arguments_for_invoke(methodHandle m, int bci) {
+ if (!profile_arguments()) {
+ return false;
+ }
+
+ if (profile_all_arguments()) {
+ return true;
+ }
+
+ assert(profile_arguments_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