8255720: Optimize bci_to_dp/-data by enabling iteration over raw DataLayouts

Reviewed-by: kvn, thartmann
This commit is contained in:
Claes Redestad 2020-11-02 13:25:11 +00:00
parent 4b775e64bd
commit 120aec7054
4 changed files with 98 additions and 28 deletions

View File

@ -335,7 +335,10 @@ ciProfileData* ciMethodData::data_at(int data_index) {
return NULL;
}
DataLayout* data_layout = data_layout_at(data_index);
return data_from(data_layout);
}
ciProfileData* ciMethodData::data_from(DataLayout* data_layout) {
switch (data_layout->tag()) {
case DataLayout::no_tag:
default:
@ -376,6 +379,16 @@ ciProfileData* ciMethodData::next_data(ciProfileData* current) {
return next;
}
DataLayout* ciMethodData::next_data_layout(DataLayout* current) {
int current_index = dp_to_di((address)current);
int next_index = current_index + current->size_in_bytes();
if (out_of_bounds(next_index)) {
return NULL;
}
DataLayout* next = data_layout_at(next_index);
return next;
}
ciProfileData* ciMethodData::bci_to_extra_data(int bci, ciMethod* m, bool& two_free_slots) {
DataLayout* dp = extra_data_base();
DataLayout* end = args_data_limit();
@ -413,12 +426,12 @@ ciProfileData* ciMethodData::bci_to_extra_data(int bci, ciMethod* m, bool& two_f
ciProfileData* ciMethodData::bci_to_data(int bci, ciMethod* m) {
// If m is not NULL we look for a SpeculativeTrapData entry
if (m == NULL) {
ciProfileData* data = data_before(bci);
for ( ; is_valid(data); data = next_data(data)) {
if (data->bci() == bci) {
set_hint_di(dp_to_di(data->dp()));
return data;
} else if (data->bci() > bci) {
DataLayout* data_layout = data_layout_before(bci);
for ( ; is_valid(data_layout); data_layout = next_data_layout(data_layout)) {
if (data_layout->bci() == bci) {
set_hint_di(dp_to_di((address)data_layout));
return data_from(data_layout);
} else if (data_layout->bci() > bci) {
break;
}
}

View File

@ -379,7 +379,7 @@ private:
// Data entries
intptr_t* _data;
// Cached hint for data_before()
// Cached hint for data_layout_before()
int _hint_di;
// Is data attached? And is it mature?
@ -445,17 +445,17 @@ private:
assert(!out_of_bounds(di), "hint_di out of bounds");
_hint_di = di;
}
ciProfileData* data_before(int bci) {
DataLayout* data_layout_before(int bci) {
// avoid SEGV on this edge case
if (data_size() == 0)
return NULL;
int hint = hint_di();
if (data_layout_at(hint)->bci() <= bci)
return data_at(hint);
return first_data();
DataLayout* layout = data_layout_at(hint_di());
if (layout->bci() <= bci)
return layout;
return data_layout_at(first_di());
}
// What is the index of the first data entry?
int first_di() { return 0; }
@ -469,6 +469,7 @@ private:
template<class T> void dump_replay_data_call_type_helper(outputStream* out, int round, int& count, T* call_type_data);
template<class T> void dump_replay_data_receiver_type_helper(outputStream* out, int round, int& count, T* call_type_data);
void dump_replay_data_extra_data_helper(outputStream* out, int round, int& count);
ciProfileData* data_from(DataLayout* data_layout);
public:
bool is_method_data() const { return true; }
@ -519,7 +520,9 @@ public:
// Walk through the data in order.
ciProfileData* first_data() { return data_at(first_di()); }
ciProfileData* next_data(ciProfileData* current);
DataLayout* next_data_layout(DataLayout* current);
bool is_valid(ciProfileData* current) { return current != NULL; }
bool is_valid(DataLayout* current) { return current != NULL; }
DataLayout* extra_data_base() const { return data_layout_at(data_size()); }
DataLayout* args_data_limit() const { return data_layout_at(data_size() + extra_data_size() -

View File

@ -1099,6 +1099,40 @@ ProfileData* MethodData::data_at(int data_index) const {
return data_layout->data_in();
}
int DataLayout::cell_count() {
switch (tag()) {
case DataLayout::no_tag:
default:
ShouldNotReachHere();
return 0;
case DataLayout::bit_data_tag:
return BitData::static_cell_count();
case DataLayout::counter_data_tag:
return CounterData::static_cell_count();
case DataLayout::jump_data_tag:
return JumpData::static_cell_count();
case DataLayout::receiver_type_data_tag:
return ReceiverTypeData::static_cell_count();
case DataLayout::virtual_call_data_tag:
return VirtualCallData::static_cell_count();
case DataLayout::ret_data_tag:
return RetData::static_cell_count();
case DataLayout::branch_data_tag:
return BranchData::static_cell_count();
case DataLayout::multi_branch_data_tag:
return ((new MultiBranchData(this))->cell_count());
case DataLayout::arg_info_data_tag:
return ((new ArgInfoData(this))->cell_count());
case DataLayout::call_type_data_tag:
return ((new CallTypeData(this))->cell_count());
case DataLayout::virtual_call_type_data_tag:
return ((new VirtualCallTypeData(this))->cell_count());
case DataLayout::parameters_type_data_tag:
return ((new ParametersTypeData(this))->cell_count());
case DataLayout::speculative_trap_data_tag:
return SpeculativeTrapData::static_cell_count();
}
}
ProfileData* DataLayout::data_in() {
switch (tag()) {
case DataLayout::no_tag:
@ -1142,6 +1176,16 @@ ProfileData* MethodData::next_data(ProfileData* current) const {
return next;
}
DataLayout* MethodData::next_data_layout(DataLayout* current) const {
int current_index = dp_to_di((address)current);
int next_index = current_index + current->size_in_bytes();
if (out_of_bounds(next_index)) {
return NULL;
}
DataLayout* next = data_layout_at(next_index);
return next;
}
// Give each of the data entries a chance to perform specific
// data initialization.
void MethodData::post_initialize(BytecodeStream* stream) {
@ -1314,13 +1358,13 @@ bool MethodData::is_mature() const {
// Translate a bci to its corresponding data index (di).
address MethodData::bci_to_dp(int bci) {
ResourceMark rm;
ProfileData* data = data_before(bci);
ProfileData* prev = NULL;
for ( ; is_valid(data); data = next_data(data)) {
DataLayout* data = data_layout_before(bci);
DataLayout* prev = NULL;
for ( ; is_valid(data); data = next_data_layout(data)) {
if (data->bci() >= bci) {
if (data->bci() == bci) set_hint_di(dp_to_di(data->dp()));
else if (prev != NULL) set_hint_di(dp_to_di(prev->dp()));
return data->dp();
if (data->bci() == bci) set_hint_di(dp_to_di((address)data));
else if (prev != NULL) set_hint_di(dp_to_di((address)prev));
return (address)data;
}
prev = data;
}
@ -1329,11 +1373,11 @@ address MethodData::bci_to_dp(int bci) {
// Translate a bci to its corresponding data, or NULL.
ProfileData* MethodData::bci_to_data(int bci) {
ProfileData* data = data_before(bci);
for ( ; is_valid(data); data = next_data(data)) {
DataLayout* data = data_layout_before(bci);
for ( ; is_valid(data); data = next_data_layout(data)) {
if (data->bci() == bci) {
set_hint_di(dp_to_di(data->dp()));
return data;
set_hint_di(dp_to_di((address)data));
return data->data_in();
} else if (data->bci() > bci) {
break;
}

View File

@ -236,6 +236,13 @@ public:
ProfileData* data_in();
int size_in_bytes() {
int cells = cell_count();
assert(cells >= 0, "invalid number of cells");
return DataLayout::compute_size_in_bytes(cells);
}
int cell_count();
// GC support
void clean_weak_klass_links(bool always_clean);
};
@ -2053,14 +2060,15 @@ private:
assert(!out_of_bounds(di), "hint_di out of bounds");
_hint_di = di;
}
ProfileData* data_before(int bci) {
DataLayout* data_layout_before(int bci) {
// avoid SEGV on this edge case
if (data_size() == 0)
return NULL;
int hint = hint_di();
if (data_layout_at(hint)->bci() <= bci)
return data_at(hint);
return first_data();
DataLayout* layout = data_layout_at(hint_di());
if (layout->bci() <= bci)
return layout;
return data_layout_at(first_di());
}
// What is the index of the first data entry?
@ -2243,7 +2251,9 @@ public:
// Walk through the data in order.
ProfileData* first_data() const { return data_at(first_di()); }
ProfileData* next_data(ProfileData* current) const;
DataLayout* next_data_layout(DataLayout* current) const;
bool is_valid(ProfileData* current) const { return current != NULL; }
bool is_valid(DataLayout* current) const { return current != NULL; }
// Convert a dp (data pointer) to a di (data index).
int dp_to_di(address dp) const {