mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
Merge
This commit is contained in:
commit
39b0e57fdd
5098 changed files with 176905 additions and 81175 deletions
|
@ -41,7 +41,7 @@
|
|||
|
||||
// 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);
|
||||
return (tag == multi_branch_data_tag) || (tag == arg_info_data_tag) || (tag == parameters_type_data_tag);
|
||||
}
|
||||
|
||||
// Perform generic initialization of the data. More specific
|
||||
|
@ -56,6 +56,11 @@ void DataLayout::initialize(u1 tag, u2 bci, int cell_count) {
|
|||
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) {
|
||||
|
@ -76,7 +81,7 @@ ProfileData::ProfileData() {
|
|||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
void ProfileData::print_shared(outputStream* st, const char* name) {
|
||||
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);
|
||||
|
@ -91,8 +96,8 @@ void ProfileData::print_shared(outputStream* st, const char* name) {
|
|||
st->print("flags(%d) ", flags);
|
||||
}
|
||||
|
||||
void ProfileData::tab(outputStream* st) {
|
||||
st->fill_to(tab_width_two);
|
||||
void ProfileData::tab(outputStream* st, bool first) const {
|
||||
st->fill_to(first ? tab_width_one : tab_width_two);
|
||||
}
|
||||
#endif // !PRODUCT
|
||||
|
||||
|
@ -104,7 +109,7 @@ void ProfileData::tab(outputStream* st) {
|
|||
|
||||
|
||||
#ifndef PRODUCT
|
||||
void BitData::print_data_on(outputStream* st) {
|
||||
void BitData::print_data_on(outputStream* st) const {
|
||||
print_shared(st, "BitData");
|
||||
}
|
||||
#endif // !PRODUCT
|
||||
|
@ -115,7 +120,7 @@ void BitData::print_data_on(outputStream* st) {
|
|||
// A CounterData corresponds to a simple counter.
|
||||
|
||||
#ifndef PRODUCT
|
||||
void CounterData::print_data_on(outputStream* st) {
|
||||
void CounterData::print_data_on(outputStream* st) const {
|
||||
print_shared(st, "CounterData");
|
||||
st->print_cr("count(%u)", count());
|
||||
}
|
||||
|
@ -145,12 +150,217 @@ void JumpData::post_initialize(BytecodeStream* stream, MethodData* mdo) {
|
|||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
void JumpData::print_data_on(outputStream* st) {
|
||||
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(Symbol* signature, bool include_receiver, int max) {
|
||||
// Parameter profiling include the receiver
|
||||
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();
|
||||
}
|
||||
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;
|
||||
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(Symbol* signature, bool has_receiver, bool include_receiver) {
|
||||
ResourceMark rm;
|
||||
int start = 0;
|
||||
// Parameter profiling include the receiver
|
||||
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) {
|
||||
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(), 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();
|
||||
}
|
||||
}
|
||||
|
||||
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(), 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();
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
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 {
|
||||
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
|
||||
//
|
||||
|
@ -169,7 +379,7 @@ void ReceiverTypeData::clean_weak_klass_links(BoolObjectClosure* is_alive_cl) {
|
|||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
void ReceiverTypeData::print_receiver_data_on(outputStream* st) {
|
||||
void ReceiverTypeData::print_receiver_data_on(outputStream* st) const {
|
||||
uint row;
|
||||
int entries = 0;
|
||||
for (row = 0; row < row_limit(); row++) {
|
||||
|
@ -190,11 +400,11 @@ void ReceiverTypeData::print_receiver_data_on(outputStream* st) {
|
|||
}
|
||||
}
|
||||
}
|
||||
void ReceiverTypeData::print_data_on(outputStream* st) {
|
||||
void ReceiverTypeData::print_data_on(outputStream* st) const {
|
||||
print_shared(st, "ReceiverTypeData");
|
||||
print_receiver_data_on(st);
|
||||
}
|
||||
void VirtualCallData::print_data_on(outputStream* st) {
|
||||
void VirtualCallData::print_data_on(outputStream* st) const {
|
||||
print_shared(st, "VirtualCallData");
|
||||
print_receiver_data_on(st);
|
||||
}
|
||||
|
@ -251,7 +461,7 @@ DataLayout* RetData::advance(MethodData *md, int bci) {
|
|||
#endif // CC_INTERP
|
||||
|
||||
#ifndef PRODUCT
|
||||
void RetData::print_data_on(outputStream* st) {
|
||||
void RetData::print_data_on(outputStream* st) const {
|
||||
print_shared(st, "RetData");
|
||||
uint row;
|
||||
int entries = 0;
|
||||
|
@ -286,7 +496,7 @@ void BranchData::post_initialize(BytecodeStream* stream, MethodData* mdo) {
|
|||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
void BranchData::print_data_on(outputStream* st) {
|
||||
void BranchData::print_data_on(outputStream* st) const {
|
||||
print_shared(st, "BranchData");
|
||||
st->print_cr("taken(%u) displacement(%d)",
|
||||
taken(), displacement());
|
||||
|
@ -360,7 +570,7 @@ void MultiBranchData::post_initialize(BytecodeStream* stream,
|
|||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
void MultiBranchData::print_data_on(outputStream* st) {
|
||||
void MultiBranchData::print_data_on(outputStream* st) const {
|
||||
print_shared(st, "MultiBranchData");
|
||||
st->print_cr("default_count(%u) displacement(%d)",
|
||||
default_count(), default_displacement());
|
||||
|
@ -374,7 +584,7 @@ void MultiBranchData::print_data_on(outputStream* st) {
|
|||
#endif
|
||||
|
||||
#ifndef PRODUCT
|
||||
void ArgInfoData::print_data_on(outputStream* st) {
|
||||
void ArgInfoData::print_data_on(outputStream* st) const {
|
||||
print_shared(st, "ArgInfoData");
|
||||
int nargs = number_of_args();
|
||||
for (int i = 0; i < nargs; i++) {
|
||||
|
@ -384,6 +594,34 @@ void ArgInfoData::print_data_on(outputStream* st) {
|
|||
}
|
||||
|
||||
#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*
|
||||
//
|
||||
|
@ -412,7 +650,11 @@ int MethodData::bytecode_cell_count(Bytecodes::Code code) {
|
|||
}
|
||||
case Bytecodes::_invokespecial:
|
||||
case Bytecodes::_invokestatic:
|
||||
return CounterData::static_cell_count();
|
||||
if (MethodData::profile_arguments() || MethodData::profile_return()) {
|
||||
return variable_cell_count;
|
||||
} else {
|
||||
return CounterData::static_cell_count();
|
||||
}
|
||||
case Bytecodes::_goto:
|
||||
case Bytecodes::_goto_w:
|
||||
case Bytecodes::_jsr:
|
||||
|
@ -420,9 +662,17 @@ int MethodData::bytecode_cell_count(Bytecodes::Code code) {
|
|||
return JumpData::static_cell_count();
|
||||
case Bytecodes::_invokevirtual:
|
||||
case Bytecodes::_invokeinterface:
|
||||
return VirtualCallData::static_cell_count();
|
||||
if (MethodData::profile_arguments() || MethodData::profile_return()) {
|
||||
return variable_cell_count;
|
||||
} else {
|
||||
return VirtualCallData::static_cell_count();
|
||||
}
|
||||
case Bytecodes::_invokedynamic:
|
||||
return CounterData::static_cell_count();
|
||||
if (MethodData::profile_arguments() || MethodData::profile_return()) {
|
||||
return variable_cell_count;
|
||||
} else {
|
||||
return CounterData::static_cell_count();
|
||||
}
|
||||
case Bytecodes::_ret:
|
||||
return RetData::static_cell_count();
|
||||
case Bytecodes::_ifeq:
|
||||
|
@ -458,7 +708,36 @@ int MethodData::compute_data_size(BytecodeStream* stream) {
|
|||
return 0;
|
||||
}
|
||||
if (cell_count == variable_cell_count) {
|
||||
cell_count = MultiBranchData::compute_cell_count(stream);
|
||||
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() || 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;
|
||||
}
|
||||
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.
|
||||
|
@ -504,6 +783,13 @@ int MethodData::compute_allocation_size_in_bytes(methodHandle method) {
|
|||
// 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);
|
||||
|
||||
// Reserve room for an area of the MDO dedicated to profiling of
|
||||
// parameters
|
||||
int args_cell = ParametersTypeData::compute_cell_count(method());
|
||||
if (args_cell > 0) {
|
||||
object_size += DataLayout::compute_size_in_bytes(args_cell);
|
||||
}
|
||||
return object_size;
|
||||
}
|
||||
|
||||
|
@ -539,10 +825,21 @@ int MethodData::initialize_data(BytecodeStream* stream,
|
|||
}
|
||||
break;
|
||||
case Bytecodes::_invokespecial:
|
||||
case Bytecodes::_invokestatic:
|
||||
cell_count = CounterData::static_cell_count();
|
||||
tag = DataLayout::counter_data_tag;
|
||||
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) {
|
||||
tag = DataLayout::call_type_data_tag;
|
||||
} else {
|
||||
tag = DataLayout::counter_data_tag;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Bytecodes::_goto:
|
||||
case Bytecodes::_goto_w:
|
||||
case Bytecodes::_jsr:
|
||||
|
@ -551,15 +848,37 @@ int MethodData::initialize_data(BytecodeStream* stream,
|
|||
tag = DataLayout::jump_data_tag;
|
||||
break;
|
||||
case Bytecodes::_invokevirtual:
|
||||
case Bytecodes::_invokeinterface:
|
||||
cell_count = VirtualCallData::static_cell_count();
|
||||
tag = DataLayout::virtual_call_data_tag;
|
||||
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) {
|
||||
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
|
||||
cell_count = CounterData::static_cell_count();
|
||||
tag = DataLayout::counter_data_tag;
|
||||
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) {
|
||||
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;
|
||||
|
@ -590,6 +909,11 @@ int MethodData::initialize_data(BytecodeStream* stream,
|
|||
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");
|
||||
if (cell_count >= 0) {
|
||||
assert(tag != DataLayout::no_tag, "bad tag");
|
||||
|
@ -636,6 +960,12 @@ ProfileData* DataLayout::data_in() {
|
|||
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);
|
||||
case DataLayout::parameters_type_data_tag:
|
||||
return new ParametersTypeData(this);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -657,6 +987,9 @@ void MethodData::post_initialize(BytecodeStream* stream) {
|
|||
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.
|
||||
|
@ -696,7 +1029,23 @@ MethodData::MethodData(methodHandle method, int size, TRAPS) {
|
|||
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);
|
||||
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 we are profiling parameters, we reserver an area near the end
|
||||
// of the MDO after the slots for bytecodes (because there's no bci
|
||||
// for method entry so they don't fit with the framework for the
|
||||
// profiling of bytecodes). We store the offset within the MDO of
|
||||
// this area (or -1 if no parameter is profiled)
|
||||
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.
|
||||
|
@ -855,6 +1204,9 @@ void MethodData::print_value_on(outputStream* st) const {
|
|||
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);
|
||||
|
@ -903,3 +1255,99 @@ 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 % 10;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue