Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8340214: C2 compilation asserts with "no node with a side effect" in PhaseIdealLoop::try_sink_out_of_loop #161

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
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
18 changes: 12 additions & 6 deletions src/hotspot/share/opto/compile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1483,12 +1483,18 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const {
} else {
ciInstanceKlass *canonical_holder = ik->get_canonical_holder(offset);
assert(offset < canonical_holder->layout_helper_size_in_bytes(), "");
if (!ik->equals(canonical_holder) || tj->offset() != offset) {
if( is_known_inst ) {
tj = to = TypeInstPtr::make(to->ptr(), canonical_holder, true, nullptr, offset, to->instance_id());
} else {
tj = to = TypeInstPtr::make(to->ptr(), canonical_holder, false, nullptr, offset);
}
assert(tj->offset() == offset, "no change to offset expected");
bool xk = to->klass_is_exact();
int instance_id = to->instance_id();

// If the input type's class is the holder: if exact, the type only includes interfaces implemented by the holder
// but if not exact, it may include extra interfaces: build new type from the holder class to make sure only
// its interfaces are included.
if (xk && ik->equals(canonical_holder)) {
assert(tj == TypeInstPtr::make(to->ptr(), canonical_holder, is_known_inst, nullptr, offset, instance_id), "exact type should be canonical type");
} else {
assert(xk || !is_known_inst, "Known instance should be exact type");
tj = to = TypeInstPtr::make(to->ptr(), canonical_holder, is_known_inst, nullptr, offset, instance_id);
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/hotspot/share/opto/graphKit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1556,6 +1556,7 @@ Node* GraphKit::make_load(Node* ctl, Node* adr, const Type* t, BasicType bt,
bool mismatched,
bool unsafe,
uint8_t barrier_data) {
assert(adr_idx == C->get_alias_index(_gvn.type(adr)->isa_ptr()), "slice of address and input slice don't match");
assert(adr_idx != Compile::AliasIdxTop, "use other make_load factory" );
const TypePtr* adr_type = nullptr; // debug-mode-only argument
debug_only(adr_type = C->get_adr_type(adr_idx));
Expand Down Expand Up @@ -1585,6 +1586,7 @@ Node* GraphKit::store_to_memory(Node* ctl, Node* adr, Node *val, BasicType bt,
bool unsafe,
int barrier_data) {
assert(adr_idx != Compile::AliasIdxTop, "use other store_to_memory factory" );
assert(adr_idx == C->get_alias_index(_gvn.type(adr)->isa_ptr()), "slice of address and input slice don't match");
const TypePtr* adr_type = nullptr;
debug_only(adr_type = C->get_adr_type(adr_idx));
Node *mem = memory(adr_idx);
Expand Down
14 changes: 8 additions & 6 deletions src/hotspot/share/opto/library_call.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2921,11 +2921,10 @@ bool LibraryCallKit::inline_native_notify_jvmti_funcs(address funcAddr, const ch
Node* thread = ideal.thread();
Node* jt_addr = basic_plus_adr(thread, in_bytes(JavaThread::is_in_VTMS_transition_offset()));
Node* vt_addr = basic_plus_adr(vt_oop, java_lang_Thread::is_in_VTMS_transition_offset());
const TypePtr *addr_type = _gvn.type(addr)->isa_ptr();

sync_kit(ideal);
access_store_at(nullptr, jt_addr, addr_type, hide, _gvn.type(hide), T_BOOLEAN, IN_NATIVE | MO_UNORDERED);
access_store_at(nullptr, vt_addr, addr_type, hide, _gvn.type(hide), T_BOOLEAN, IN_NATIVE | MO_UNORDERED);
access_store_at(nullptr, jt_addr, _gvn.type(jt_addr)->is_ptr(), hide, _gvn.type(hide), T_BOOLEAN, IN_NATIVE | MO_UNORDERED);
access_store_at(nullptr, vt_addr, _gvn.type(vt_addr)->is_ptr(), hide, _gvn.type(hide), T_BOOLEAN, IN_NATIVE | MO_UNORDERED);

ideal.sync_kit(this);
} ideal.end_if();
Expand Down Expand Up @@ -3283,7 +3282,9 @@ bool LibraryCallKit::inline_native_getEventWriter() {

// Load the raw epoch value from the threadObj.
Node* threadObj_epoch_offset = basic_plus_adr(threadObj, java_lang_Thread::jfr_epoch_offset());
Node* threadObj_epoch_raw = access_load_at(threadObj, threadObj_epoch_offset, TypeRawPtr::BOTTOM, TypeInt::CHAR, T_CHAR,
Node* threadObj_epoch_raw = access_load_at(threadObj, threadObj_epoch_offset,
_gvn.type(threadObj_epoch_offset)->isa_ptr(),
TypeInt::CHAR, T_CHAR,
IN_HEAP | MO_UNORDERED | C2_MISMATCHED | C2_CONTROL_DEPENDENT_LOAD);

// Mask off the excluded information from the epoch.
Expand All @@ -3298,7 +3299,8 @@ bool LibraryCallKit::inline_native_getEventWriter() {

// Load the raw epoch value from the vthread.
Node* vthread_epoch_offset = basic_plus_adr(vthread, java_lang_Thread::jfr_epoch_offset());
Node* vthread_epoch_raw = access_load_at(vthread, vthread_epoch_offset, TypeRawPtr::BOTTOM, TypeInt::CHAR, T_CHAR,
Node* vthread_epoch_raw = access_load_at(vthread, vthread_epoch_offset, _gvn.type(vthread_epoch_offset)->is_ptr(),
TypeInt::CHAR, T_CHAR,
IN_HEAP | MO_UNORDERED | C2_MISMATCHED | C2_CONTROL_DEPENDENT_LOAD);

// Mask off the excluded information from the epoch.
Expand Down Expand Up @@ -3534,7 +3536,7 @@ void LibraryCallKit::extend_setCurrentThread(Node* jt, Node* thread) {

// Load the raw epoch value from the vthread.
Node* epoch_offset = basic_plus_adr(thread, java_lang_Thread::jfr_epoch_offset());
Node* epoch_raw = access_load_at(thread, epoch_offset, TypeRawPtr::BOTTOM, TypeInt::CHAR, T_CHAR,
Node* epoch_raw = access_load_at(thread, epoch_offset, _gvn.type(epoch_offset)->is_ptr(), TypeInt::CHAR, T_CHAR,
IN_HEAP | MO_UNORDERED | C2_MISMATCHED | C2_CONTROL_DEPENDENT_LOAD);

// Mask off the excluded information from the epoch.
Expand Down
101 changes: 101 additions & 0 deletions test/hotspot/jtreg/compiler/types/TestBadMemSliceWithInterfaces.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* Copyright (c) 2024, Red Hat, Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

/**
* @test
* @bug 8340214
* @summary C2 compilation asserts with "no node with a side effect" in PhaseIdealLoop::try_sink_out_of_loop
*
* @run main/othervm -XX:-BackgroundCompilation TestBadMemSliceWithInterfaces
*
*/

public class TestBadMemSliceWithInterfaces {
public static void main(String[] args) {
B b = new B();
C c = new C();
for (int i = 0; i < 20_000; i++) {
test1(b, c, true);
test1(b, c, false);
b.field = 0;
c.field = 0;
int res = test2(b, c, true);
if (res != 42) {
throw new RuntimeException("incorrect result " + res);
}
res = test2(b, c, false);
if (res != 42) {
throw new RuntimeException("incorrect result " + res);
}
}
}

private static void test1(B b, C c, boolean flag) {
A a;
if (flag) {
a = b;
} else {
a = c;
}
for (int i = 0; i < 1000; i++) {
a.field = 42;
}
}

private static int test2(B b, C c, boolean flag) {
A a;
if (flag) {
a = b;
} else {
a = c;
}
int v = 0;
for (int i = 0; i < 2; i++) {
v += a.field;
a.field = 42;
}
return v;
}

interface I {
void m();
}

static class A {
int field;
}

static class B extends A implements I {
@Override
public void m() {

}
}

static class C extends A implements I {
@Override
public void m() {

}
}
}