8340214: C2 compilation asserts with "no node with a side effect" in PhaseIdealLoop::try_sink_out_of_loop
Reviewed-by: chagedorn, thartmann
This commit is contained in:
parent
ecc77a5b4a
commit
ff2f39f240
@ -1466,12 +1466,18 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const {
|
|||||||
} else {
|
} else {
|
||||||
ciInstanceKlass *canonical_holder = ik->get_canonical_holder(offset);
|
ciInstanceKlass *canonical_holder = ik->get_canonical_holder(offset);
|
||||||
assert(offset < canonical_holder->layout_helper_size_in_bytes(), "");
|
assert(offset < canonical_holder->layout_helper_size_in_bytes(), "");
|
||||||
if (!ik->equals(canonical_holder) || tj->offset() != offset) {
|
assert(tj->offset() == offset, "no change to offset expected");
|
||||||
if( is_known_inst ) {
|
bool xk = to->klass_is_exact();
|
||||||
tj = to = TypeInstPtr::make(to->ptr(), canonical_holder, true, nullptr, offset, to->instance_id());
|
int instance_id = to->instance_id();
|
||||||
} else {
|
|
||||||
tj = to = TypeInstPtr::make(to->ptr(), canonical_holder, false, nullptr, offset);
|
// 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1558,6 +1558,7 @@ Node* GraphKit::make_load(Node* ctl, Node* adr, const Type* t, BasicType bt,
|
|||||||
bool mismatched,
|
bool mismatched,
|
||||||
bool unsafe,
|
bool unsafe,
|
||||||
uint8_t barrier_data) {
|
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" );
|
assert(adr_idx != Compile::AliasIdxTop, "use other make_load factory" );
|
||||||
const TypePtr* adr_type = nullptr; // debug-mode-only argument
|
const TypePtr* adr_type = nullptr; // debug-mode-only argument
|
||||||
debug_only(adr_type = C->get_adr_type(adr_idx));
|
debug_only(adr_type = C->get_adr_type(adr_idx));
|
||||||
@ -1587,6 +1588,7 @@ Node* GraphKit::store_to_memory(Node* ctl, Node* adr, Node *val, BasicType bt,
|
|||||||
bool unsafe,
|
bool unsafe,
|
||||||
int barrier_data) {
|
int barrier_data) {
|
||||||
assert(adr_idx != Compile::AliasIdxTop, "use other store_to_memory factory" );
|
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;
|
const TypePtr* adr_type = nullptr;
|
||||||
debug_only(adr_type = C->get_adr_type(adr_idx));
|
debug_only(adr_type = C->get_adr_type(adr_idx));
|
||||||
Node *mem = memory(adr_idx);
|
Node *mem = memory(adr_idx);
|
||||||
|
@ -2959,11 +2959,10 @@ bool LibraryCallKit::inline_native_notify_jvmti_funcs(address funcAddr, const ch
|
|||||||
Node* thread = ideal.thread();
|
Node* thread = ideal.thread();
|
||||||
Node* jt_addr = basic_plus_adr(thread, in_bytes(JavaThread::is_in_VTMS_transition_offset()));
|
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());
|
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);
|
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, jt_addr, _gvn.type(jt_addr)->is_ptr(), 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, vt_addr, _gvn.type(vt_addr)->is_ptr(), hide, _gvn.type(hide), T_BOOLEAN, IN_NATIVE | MO_UNORDERED);
|
||||||
|
|
||||||
ideal.sync_kit(this);
|
ideal.sync_kit(this);
|
||||||
} ideal.end_if();
|
} ideal.end_if();
|
||||||
@ -3325,7 +3324,9 @@ bool LibraryCallKit::inline_native_getEventWriter() {
|
|||||||
|
|
||||||
// Load the raw epoch value from the threadObj.
|
// 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_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);
|
IN_HEAP | MO_UNORDERED | C2_MISMATCHED | C2_CONTROL_DEPENDENT_LOAD);
|
||||||
|
|
||||||
// Mask off the excluded information from the epoch.
|
// Mask off the excluded information from the epoch.
|
||||||
@ -3344,7 +3345,8 @@ bool LibraryCallKit::inline_native_getEventWriter() {
|
|||||||
|
|
||||||
// Load the raw epoch value from the vthread.
|
// 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_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);
|
IN_HEAP | MO_UNORDERED | C2_MISMATCHED | C2_CONTROL_DEPENDENT_LOAD);
|
||||||
|
|
||||||
// Mask off the excluded information from the epoch.
|
// Mask off the excluded information from the epoch.
|
||||||
@ -3590,7 +3592,7 @@ void LibraryCallKit::extend_setCurrentThread(Node* jt, Node* thread) {
|
|||||||
|
|
||||||
// Load the raw epoch value from the vthread.
|
// Load the raw epoch value from the vthread.
|
||||||
Node* epoch_offset = basic_plus_adr(thread, java_lang_Thread::jfr_epoch_offset());
|
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);
|
IN_HEAP | MO_UNORDERED | C2_MISMATCHED | C2_CONTROL_DEPENDENT_LOAD);
|
||||||
|
|
||||||
// Mask off the excluded information from the epoch.
|
// Mask off the excluded information from the epoch.
|
||||||
|
@ -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() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user