< prev index next >
src/share/vm/ci/ciMethodData.cpp
Print this page
rev 9358 : 8057038: Speculative traps not robust when compilation and class unloading are concurrent
Summary: speculative traps can be removed from MDO while being copied by compiler
Reviewed-by: kvn, iveresov
*** 79,101 ****
}
void ciMethodData::load_extra_data() {
MethodData* mdo = get_MethodData();
// speculative trap entries also hold a pointer to a Method so need to be translated
DataLayout* dp_src = mdo->extra_data_base();
! DataLayout* end_src = mdo->extra_data_limit();
DataLayout* dp_dst = extra_data_base();
for (;; dp_src = MethodData::next_extra(dp_src), dp_dst = MethodData::next_extra(dp_dst)) {
assert(dp_src < end_src, "moved past end of extra data");
! // New traps in the MDO can be added as we translate the copy so
! // look at the entries in the copy.
! switch(dp_dst->tag()) {
case DataLayout::speculative_trap_data_tag: {
ciSpeculativeTrapData* data_dst = new ciSpeculativeTrapData(dp_dst);
SpeculativeTrapData* data_src = new SpeculativeTrapData(dp_src);
data_dst->translate_from(data_src);
break;
}
case DataLayout::bit_data_tag:
break;
case DataLayout::no_tag:
--- 79,119 ----
}
void ciMethodData::load_extra_data() {
MethodData* mdo = get_MethodData();
+ MutexLocker(mdo->extra_data_lock());
+
// speculative trap entries also hold a pointer to a Method so need to be translated
DataLayout* dp_src = mdo->extra_data_base();
! DataLayout* end_src = mdo->args_data_limit();
DataLayout* dp_dst = extra_data_base();
for (;; dp_src = MethodData::next_extra(dp_src), dp_dst = MethodData::next_extra(dp_dst)) {
assert(dp_src < end_src, "moved past end of extra data");
! assert(((intptr_t)dp_dst) - ((intptr_t)extra_data_base()) == ((intptr_t)dp_src) - ((intptr_t)mdo->extra_data_base()), "source and destination don't match");
! // New traps in the MDO may have been added since we copied the
! // data (concurrent deoptimizations before we acquired
! // extra_data_lock above) or can be removed (a safepoint may occur
! // in the translate_from call below) as we translate the copy:
! // update the copy as we go.
! int tag = dp_src->tag();
! if (tag != DataLayout::arg_info_data_tag) {
! memcpy(dp_dst, dp_src, ((intptr_t)MethodData::next_extra(dp_src)) - ((intptr_t)dp_src));
! }
!
! switch(tag) {
case DataLayout::speculative_trap_data_tag: {
ciSpeculativeTrapData* data_dst = new ciSpeculativeTrapData(dp_dst);
SpeculativeTrapData* data_src = new SpeculativeTrapData(dp_src);
+
data_dst->translate_from(data_src);
+
+ #ifdef ASSERT
+ SpeculativeTrapData* data_src2 = new SpeculativeTrapData(dp_src);
+ assert(data_src2->method() == data_src->method() && data_src2->bci() == data_src->bci(), "entries changed while translating");
+ #endif
+
break;
}
case DataLayout::bit_data_tag:
break;
case DataLayout::no_tag:
*** 242,254 ****
ciProfileData* next = data_at(next_index);
return next;
}
ciProfileData* ciMethodData::bci_to_extra_data(int bci, ciMethod* m, bool& two_free_slots) {
! // bci_to_extra_data(bci) ...
! DataLayout* dp = data_layout_at(data_size());
! DataLayout* end = data_layout_at(data_size() + extra_data_size());
two_free_slots = false;
for (;dp < end; dp = MethodData::next_extra(dp)) {
switch(dp->tag()) {
case DataLayout::no_tag:
_saw_free_extra_data = true; // observed an empty slot (common case)
--- 260,271 ----
ciProfileData* next = data_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();
two_free_slots = false;
for (;dp < end; dp = MethodData::next_extra(dp)) {
switch(dp->tag()) {
case DataLayout::no_tag:
_saw_free_extra_data = true; // observed an empty slot (common case)
*** 495,506 ****
return in_ByteSize(offset);
}
ciArgInfoData *ciMethodData::arg_info() const {
// Should be last, have to skip all traps.
! DataLayout* dp = data_layout_at(data_size());
! DataLayout* end = data_layout_at(data_size() + extra_data_size());
for (; dp < end; dp = MethodData::next_extra(dp)) {
if (dp->tag() == DataLayout::arg_info_data_tag)
return new ciArgInfoData(dp);
}
return NULL;
--- 512,523 ----
return in_ByteSize(offset);
}
ciArgInfoData *ciMethodData::arg_info() const {
// Should be last, have to skip all traps.
! DataLayout* dp = extra_data_base();
! DataLayout* end = args_data_limit();
for (; dp < end; dp = MethodData::next_extra(dp)) {
if (dp->tag() == DataLayout::arg_info_data_tag)
return new ciArgInfoData(dp);
}
return NULL;
*** 597,608 ****
st->print("%d", dp_to_di(data->dp()));
st->fill_to(6);
data->print_data_on(st);
}
st->print_cr("--- Extra data:");
! DataLayout* dp = data_layout_at(data_size());
! DataLayout* end = data_layout_at(data_size() + extra_data_size());
for (;; dp = MethodData::next_extra(dp)) {
assert(dp < end, "moved past end of extra data");
switch (dp->tag()) {
case DataLayout::no_tag:
continue;
--- 614,625 ----
st->print("%d", dp_to_di(data->dp()));
st->fill_to(6);
data->print_data_on(st);
}
st->print_cr("--- Extra data:");
! DataLayout* dp = extra_data_base();
! DataLayout* end = args_data_limit();
for (;; dp = MethodData::next_extra(dp)) {
assert(dp < end, "moved past end of extra data");
switch (dp->tag()) {
case DataLayout::no_tag:
continue;
< prev index next >