mirror of
https://github.com/openjdk/jdk.git
synced 2026-07-02 07:10:23 +00:00
8387395: [REDO] C2: SIGSEGV in compiled code due to missing ctrl
Reviewed-by: dlong, kvn, vlivanov
This commit is contained in:
parent
b186074751
commit
28c79eb792
@ -3497,22 +3497,38 @@ void Compile::final_graph_reshaping_main_switch(Node* n, Final_Reshape_Counts& f
|
||||
ResourceMark rm;
|
||||
Unique_Node_List wq;
|
||||
wq.push(n);
|
||||
|
||||
|
||||
// When we remove a CastPP, we need to pin all of its transitive users under the control of
|
||||
// the removed node. The simplest approach is to pin all of the uses of the removed CastPP,
|
||||
// but it is overly conservative, as an AddP does not really need pinning. As a result, we
|
||||
// look through those nodes that do not need pinning and only pin memory access nodes under
|
||||
// n->in(0).
|
||||
for (uint next = 0; next < wq.size(); ++next) {
|
||||
Node *m = wq.at(next);
|
||||
for (DUIterator_Fast imax, i = m->fast_outs(imax); i < imax; i++) {
|
||||
Node* use = m->fast_out(i);
|
||||
if (use->is_Mem() || use->is_EncodeNarrowPtr()) {
|
||||
int use_op = use->Opcode();
|
||||
if (use->is_CFG() || use->pinned() || // already pinned at the exact control
|
||||
use->is_Cmp() || use_op == Op_CastP2X || use_op == Op_Conv2B) { // pure computations
|
||||
continue;
|
||||
} else if (use->is_EncodeNarrowPtr() || // EncodeP remembers whether its input is nullable, so it must be pinned
|
||||
use_op == Op_PartialSubtypeCheck || // This accesses its pointer inputs, so it must depend on them being not-null
|
||||
use->is_Mem() || use->is_memory_access_intrinsic()) {
|
||||
use->ensure_control_or_add_prec(n->in(0));
|
||||
} else if (use_op == Op_AddP ||
|
||||
use_op == Op_CastPP || use_op == Op_CheckCastPP ||
|
||||
use_op == Op_CMoveP || use_op == Op_CMoveN ||
|
||||
use_op == Op_DecodeN || use_op == Op_DecodeNKlass ||
|
||||
use_op == Op_VerifyVectorAlignment) {
|
||||
// Look through use to find memory accesses if use does not need pinning
|
||||
wq.push(use);
|
||||
} else {
|
||||
switch(use->Opcode()) {
|
||||
case Op_AddP:
|
||||
case Op_DecodeN:
|
||||
case Op_DecodeNKlass:
|
||||
case Op_CheckCastPP:
|
||||
case Op_CastPP:
|
||||
wq.push(use);
|
||||
break;
|
||||
}
|
||||
// Should have handled all kinds of nodes, verify that we do not unexpectedly arrive
|
||||
// here
|
||||
assert(false, "unexpected node %s", use->Name());
|
||||
// Be conservative in product and pin the unexpected use
|
||||
use->ensure_control_or_add_prec(n->in(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3018,6 +3018,27 @@ bool Node::is_data_proj_of_pure_function(const Node* maybe_pure_function) const
|
||||
return Opcode() == Op_Proj && as_Proj()->_con == TypeFunc::Parms && maybe_pure_function->is_CallLeafPure();
|
||||
}
|
||||
|
||||
// Whether this is an intrinsic node that accesses memory and has a memory input, such as array
|
||||
// equal intrinsic. Some nodes do access memory but do not have a memory input, such as
|
||||
// PartialSubTypeCheck, they are not included here.
|
||||
bool Node::is_memory_access_intrinsic() const {
|
||||
switch (Opcode()) {
|
||||
case Op_StrComp:
|
||||
case Op_StrEquals:
|
||||
case Op_StrIndexOf:
|
||||
case Op_StrIndexOfChar:
|
||||
case Op_StrCompressedCopy:
|
||||
case Op_StrInflatedCopy:
|
||||
case Op_AryEq:
|
||||
case Op_CountPositives:
|
||||
case Op_VectorizedHashCode:
|
||||
case Op_EncodeISOArray:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------has_non_debug_uses------------------------------
|
||||
// Checks whether the node has any non-debug uses or not.
|
||||
bool Node::has_non_debug_uses() const {
|
||||
|
||||
@ -1069,6 +1069,7 @@ public:
|
||||
uint is_Copy() const { return (_flags & Flag_is_Copy); }
|
||||
|
||||
virtual bool is_CFG() const { return false; }
|
||||
bool is_memory_access_intrinsic() const;
|
||||
|
||||
// If this node is control-dependent on a test, can it be rerouted to a dominating equivalent
|
||||
// test? This means that the node can be executed safely as long as it happens after the test
|
||||
|
||||
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2026, Oracle and/or its affiliates. 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.
|
||||
*/
|
||||
package compiler.controldependency;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8385420
|
||||
* @summary C2 correctly handles the case when the removed CastPPNode has a CMove use.
|
||||
* @run main ${test.main.class}
|
||||
* @run main/othervm -Xbatch -XX:CompileOnly=${test.main.class}::test
|
||||
* -XX:+UnlockDiagnosticVMOptions -XX:+StressGCM ${test.main.class}
|
||||
*
|
||||
*/
|
||||
public class TestRemoveCastPPWithCMoveUse {
|
||||
public static void main(String[] args) {
|
||||
for (int i = 0; i < 10_000; i++) {
|
||||
test(null, false);
|
||||
test(null, true);
|
||||
test("", false);
|
||||
test("", true);
|
||||
}
|
||||
}
|
||||
|
||||
static int test(String a, boolean flag) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (a == null) {
|
||||
sb.append("");
|
||||
} else {
|
||||
sb.append(flag ? a : "");
|
||||
}
|
||||
return sb.length();
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user