Skip to content

Commit 176422b

Browse files
8370519: C2: Hit MemLimit when running with +VerifyLoopOptimizations
Co-authored-by: Benoît Maillard <bmaillard@openjdk.org> Reviewed-by: mhaessig, bmaillard, epeter
1 parent 17f25b5 commit 176422b

File tree

4 files changed

+157
-24
lines changed

4 files changed

+157
-24
lines changed

src/hotspot/share/memory/arena.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -101,6 +101,7 @@ class Chunk {
101101
FN(ra, Resource areas) \
102102
FN(node, C2 Node arena) \
103103
FN(comp, C2 Compile arena) \
104+
FN(idealloop, C2 Ideal Loop arena) \
104105
FN(type, C2 Type arena) \
105106
FN(states, C2 Matcher States Arena) \
106107
FN(reglive, C2 Register Allocation Live Arenas) \

src/hotspot/share/opto/loopnode.cpp

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1998, 2026, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -3752,6 +3752,20 @@ void CountedLoopEndNode::dump_spec(outputStream *st) const {
37523752
}
37533753
#endif
37543754

3755+
IdealLoopTree::IdealLoopTree(PhaseIdealLoop* phase, Node* head, Node* tail): _parent(nullptr), _next(nullptr), _child(nullptr),
3756+
_head(head), _tail(tail),
3757+
_phase(phase),
3758+
_local_loop_unroll_limit(0), _local_loop_unroll_factor(0),
3759+
_body(phase->arena()),
3760+
_nest(0), _irreducible(0), _has_call(0), _has_sfpt(0), _rce_candidate(0),
3761+
_has_range_checks(0), _has_range_checks_computed(0),
3762+
_safepts(nullptr),
3763+
_required_safept(nullptr),
3764+
_allow_optimizations(true) {
3765+
precond(_head != nullptr);
3766+
precond(_tail != nullptr);
3767+
}
3768+
37553769
//=============================================================================
37563770
//------------------------------is_member--------------------------------------
37573771
// Is 'l' a member of 'this'?
@@ -5089,8 +5103,8 @@ void PhaseIdealLoop::build_and_optimize() {
50895103
// Since nodes do not have a slot for immediate dominator, make
50905104
// a persistent side array for that info indexed on node->_idx.
50915105
_idom_size = C->unique();
5092-
_idom = NEW_RESOURCE_ARRAY( Node*, _idom_size );
5093-
_dom_depth = NEW_RESOURCE_ARRAY( uint, _idom_size );
5106+
_idom = NEW_ARENA_ARRAY(&_arena, Node*, _idom_size);
5107+
_dom_depth = NEW_ARENA_ARRAY(&_arena, uint, _idom_size);
50945108
_dom_stk = nullptr; // Allocated on demand in recompute_dom_depth
50955109
memset( _dom_depth, 0, _idom_size * sizeof(uint) );
50965110

@@ -5691,8 +5705,8 @@ void PhaseIdealLoop::set_idom(Node* d, Node* n, uint dom_depth) {
56915705
uint idx = d->_idx;
56925706
if (idx >= _idom_size) {
56935707
uint newsize = next_power_of_2(idx);
5694-
_idom = REALLOC_RESOURCE_ARRAY( Node*, _idom,_idom_size,newsize);
5695-
_dom_depth = REALLOC_RESOURCE_ARRAY( uint, _dom_depth,_idom_size,newsize);
5708+
_idom = REALLOC_ARENA_ARRAY(&_arena, Node*, _idom,_idom_size,newsize);
5709+
_dom_depth = REALLOC_ARENA_ARRAY(&_arena, uint, _dom_depth,_idom_size,newsize);
56965710
memset( _dom_depth + _idom_size, 0, (newsize - _idom_size) * sizeof(uint) );
56975711
_idom_size = newsize;
56985712
}

src/hotspot/share/opto/loopnode.hpp

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1998, 2026, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -669,21 +669,7 @@ class IdealLoopTree : public ResourceObj {
669669
Node_List* _required_safept; // A inner loop cannot delete these safepts;
670670
bool _allow_optimizations; // Allow loop optimizations
671671

672-
IdealLoopTree( PhaseIdealLoop* phase, Node *head, Node *tail )
673-
: _parent(nullptr), _next(nullptr), _child(nullptr),
674-
_head(head), _tail(tail),
675-
_phase(phase),
676-
_local_loop_unroll_limit(0), _local_loop_unroll_factor(0),
677-
_body(Compile::current()->comp_arena()),
678-
_nest(0), _irreducible(0), _has_call(0), _has_sfpt(0), _rce_candidate(0),
679-
_has_range_checks(0), _has_range_checks_computed(0),
680-
_safepts(nullptr),
681-
_required_safept(nullptr),
682-
_allow_optimizations(true)
683-
{
684-
precond(_head != nullptr);
685-
precond(_tail != nullptr);
686-
}
672+
IdealLoopTree(PhaseIdealLoop* phase, Node* head, Node* tail);
687673

688674
// Is 'l' a member of 'this'?
689675
bool is_member(const IdealLoopTree *l) const; // Test for nested membership
@@ -889,6 +875,8 @@ class PhaseIdealLoop : public PhaseTransform {
889875
friend class ShenandoahBarrierC2Support;
890876
friend class AutoNodeBudget;
891877

878+
Arena _arena; // For data whose lifetime is a single pass of loop optimizations
879+
892880
// Map loop membership for CFG nodes, and ctrl for non-CFG nodes.
893881
//
894882
// Exception: dead CFG nodes may instead have a ctrl/idom forwarding
@@ -1049,6 +1037,8 @@ class PhaseIdealLoop : public PhaseTransform {
10491037

10501038
PhaseIterGVN &igvn() const { return _igvn; }
10511039

1040+
Arena* arena() { return &_arena; };
1041+
10521042
bool has_node(const Node* n) const {
10531043
guarantee(n != nullptr, "No Node.");
10541044
return _loop_or_ctrl[n->_idx] != nullptr;
@@ -1223,7 +1213,8 @@ class PhaseIdealLoop : public PhaseTransform {
12231213
// Compute the Ideal Node to Loop mapping
12241214
PhaseIdealLoop(PhaseIterGVN& igvn, LoopOptsMode mode) :
12251215
PhaseTransform(Ideal_Loop),
1226-
_loop_or_ctrl(igvn.C->comp_arena()),
1216+
_arena(mtCompiler, Arena::Tag::tag_idealloop),
1217+
_loop_or_ctrl(&_arena),
12271218
_igvn(igvn),
12281219
_verify_me(nullptr),
12291220
_verify_only(false),
@@ -1238,7 +1229,8 @@ class PhaseIdealLoop : public PhaseTransform {
12381229
// or only verify that the graph is valid if verify_me is null.
12391230
PhaseIdealLoop(PhaseIterGVN& igvn, const PhaseIdealLoop* verify_me = nullptr) :
12401231
PhaseTransform(Ideal_Loop),
1241-
_loop_or_ctrl(igvn.C->comp_arena()),
1232+
_arena(mtCompiler, Arena::Tag::tag_idealloop),
1233+
_loop_or_ctrl(&_arena),
12421234
_igvn(igvn),
12431235
_verify_me(verify_me),
12441236
_verify_only(verify_me == nullptr),
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
/*
2+
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
/**
25+
* @test
26+
* @key stress randomness
27+
* @bug 8370519
28+
* @summary C2: Hit MemLimit when running with +VerifyLoopOptimizations
29+
* @run main/othervm -XX:CompileCommand=compileonly,${test.main.class}::* -XX:-TieredCompilation -Xbatch
30+
* -XX:+UnlockDiagnosticVMOptions -XX:+IgnoreUnrecognizedVMOptions
31+
* -XX:+StressLoopPeeling -XX:+VerifyLoopOptimizations
32+
* -XX:CompileCommand=memlimit,${test.main.class}::*,600M~crash
33+
* -XX:StressSeed=3106998670 ${test.main.class}
34+
* @run main ${test.main.class}
35+
*/
36+
37+
package compiler.c2;
38+
39+
public class TestVerifyLoopOptimizationsHighMemUsage {
40+
public static final int N = 400;
41+
public static long instanceCount = -13L;
42+
public static volatile short sFld = -16143;
43+
public static int iFld = -159;
44+
public static float fArrFld[] = new float[N];
45+
46+
public static long lMeth(int i1) {
47+
int i2 = 11, i3 = 37085, i4 = 177, i5 = 190, i6 = -234, i7 = 13060,
48+
iArr[] = new int[N];
49+
float f = 1.179F;
50+
double d = 2.9685;
51+
long lArr[] = new long[N];
52+
for (i2 = 15; i2 < 330; ++i2)
53+
for (i4 = 1; i4 < 5; ++i4) {
54+
fArrFld[i4 + 1] = (++i1);
55+
for (i6 = 2; i6 > 1; i6 -= 3)
56+
switch ((i2 * 5) + 54) {
57+
case 156:
58+
if (i4 != 0)
59+
;
60+
case 168:
61+
case 342:
62+
case 283:
63+
case 281:
64+
case 328:
65+
case 322:
66+
case 228:
67+
case 114:
68+
case 207:
69+
case 209:
70+
case 354:
71+
case 108:
72+
i1 <<= i1;
73+
case 398:
74+
case 144:
75+
case 218:
76+
case 116:
77+
case 296:
78+
case 198:
79+
case 173:
80+
case 105:
81+
case 120:
82+
case 248:
83+
case 140:
84+
case 352:
85+
try {
86+
} catch (ArithmeticException a_e) {
87+
}
88+
case 404:
89+
i5 += (i6 ^ instanceCount);
90+
case 370:
91+
case 211:
92+
case 231:
93+
try {
94+
} catch (ArithmeticException a_e) {
95+
}
96+
case 251:
97+
case 179:
98+
f += (((i6 * sFld) + i4) -
99+
iFld);
100+
}
101+
}
102+
long meth_res = i1 + i2 + i3 + i4 + i5 + i6 + i7 + Float.floatToIntBits(f) +
103+
Double.doubleToLongBits(d) + +checkSum(iArr) +
104+
checkSum(lArr);
105+
return meth_res;
106+
}
107+
108+
public static long checkSum(int[] a) {
109+
long sum = 0;
110+
for (int j = 0; j < a.length; j++)
111+
sum += (a[j] / (j + 1) + a[j] % (j + 1));
112+
return sum;
113+
}
114+
115+
public static long checkSum(long[] a) {
116+
long sum = 0;
117+
for (int j = 0; j < a.length; j++)
118+
sum += (a[j] / (j + 1) + a[j] % (j + 1));
119+
return sum;
120+
}
121+
122+
public static void main(String[] strArr) {
123+
for (int i = 0; i < 10; i++)
124+
lMeth(-159);
125+
}
126+
}

0 commit comments

Comments
 (0)