Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions src/hotspot/share/c1/c1_LIRGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2380,6 +2380,7 @@ void LIRGenerator::do_LoadIndexed(LoadIndexed* x) {
} else {
LIR_Opr result = rlock_result(x, x->elt_type());
LoadFlattenedArrayStub* slow_path = nullptr;
LIR_Opr load_result = result;

if (x->should_profile() && x->array()->maybe_null_free_array()) {
profile_null_free_array(array, md, data);
Expand All @@ -2388,19 +2389,25 @@ void LIRGenerator::do_LoadIndexed(LoadIndexed* x) {
if (x->elt_type() == T_OBJECT && x->array()->maybe_flat_array()) {
assert(x->delayed() == nullptr, "Delayed LoadIndexed only apply to loaded_flat_arrays");
index.load_item();
// if we are loading from a flat array, load it using a runtime call
slow_path = new LoadFlattenedArrayStub(array.result(), index.result(), result, state_for(x, x->state_before()));
// Use a temporary for the conditional load so that the RA defines
// 'result' at the continuation point (after both paths merge).
// Otherwise, the RA may insert a spill at the load's def point
// (inside the conditional code), and the stub's continuation jump
// would skip that spill, leaving the spill slot stale.
load_result = new_register(T_OBJECT);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the rlock_result just above in line 2381 do exactly that?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to detect spills in conditional code at compile time.

I'm not convinced creating a new virtual register for "load_result" here is correct either. It moves the problem to a different virtual register, one that has a shorter lifetime that "result", but does that guarantee there won't be a spill? We are still setting a register in two different paths that are invisible to C1 LIR.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with Dean. I think it's the same problem I described in JDK-8353851.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe setting LIRGenerator::set_in_conditional_code here like we do as mitigation in Load/StoreIndexed would help?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dean-long @TobiHartmann Hi, I'm so sorry for being late.
I think this is the same issue as JDK-8353851.

Maybe setting LIRGenerator::set_in_conditional_code here like we do as mitigation in Load/StoreIndexed would help?

I will try this fix.

slow_path = new LoadFlattenedArrayStub(array.result(), index.result(), load_result, state_for(x, x->state_before()));
check_flat_array(array.result(), slow_path);
set_in_conditional_code(true);
}

DecoratorSet decorators = IN_HEAP | IS_ARRAY;
access_load_at(decorators, x->elt_type(),
array, index.result(), result,
array, index.result(), load_result,
nullptr, null_check_info);

if (slow_path != nullptr) {
__ branch_destination(slow_path->continuation());
__ move(load_result, result);
set_in_conditional_code(false);
}

Expand Down