Skip to content

Commit 63e611c

Browse files
committed
8335334: Stress mode to randomly execute unstable if traps
Reviewed-by: chagedorn, kvn
1 parent 37ec80d commit 63e611c

File tree

15 files changed

+110
-10
lines changed

15 files changed

+110
-10
lines changed

src/hotspot/share/opto/c2_globals.hpp

+3
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@
5858
product(bool, StressMacroExpansion, false, DIAGNOSTIC, \
5959
"Randomize macro node expansion order") \
6060
\
61+
product(bool, StressUnstableIfTraps, false, DIAGNOSTIC, \
62+
"Randomly take unstable if traps") \
63+
\
6164
product(uint, StressSeed, 0, DIAGNOSTIC, \
6265
"Seed for randomized stress testing (if unset, a random one is " \
6366
"generated). The seed is recorded in the compilation log, if " \

src/hotspot/share/opto/cfgnode.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,6 @@ class IfNode : public MultiBranchNode {
347347
bool is_null_check(ProjNode* proj, PhaseIterGVN* igvn);
348348
bool is_side_effect_free_test(ProjNode* proj, PhaseIterGVN* igvn);
349349
void reroute_side_effect_free_unc(ProjNode* proj, ProjNode* dom_proj, PhaseIterGVN* igvn);
350-
ProjNode* uncommon_trap_proj(CallStaticJavaNode*& call) const;
351350
bool fold_compares_helper(ProjNode* proj, ProjNode* success, ProjNode* fail, PhaseIterGVN* igvn);
352351
static bool is_dominator_unc(CallStaticJavaNode* dom_unc, CallStaticJavaNode* unc);
353352

@@ -442,6 +441,7 @@ class IfNode : public MultiBranchNode {
442441
static Node* up_one_dom(Node* curr, bool linear_only = false);
443442
bool is_zero_trip_guard() const;
444443
Node* dominated_by(Node* prev_dom, PhaseIterGVN* igvn, bool pin_array_access_nodes);
444+
ProjNode* uncommon_trap_proj(CallStaticJavaNode*& call, Deoptimization::DeoptReason reason = Deoptimization::Reason_none) const;
445445

446446
// Takes the type of val and filters it through the test represented
447447
// by if_proj and returns a more refined type if one is produced.

src/hotspot/share/opto/compile.cpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,11 @@ Compile::Compile( ciEnv* ci_env, ciMethod* target, int osr_bci,
719719
method()->ensure_method_data();
720720
}
721721

722+
if (StressLCM || StressGCM || StressIGVN || StressCCP ||
723+
StressIncrementalInlining || StressMacroExpansion || StressUnstableIfTraps) {
724+
initialize_stress_seed(directive);
725+
}
726+
722727
Init(/*do_aliasing=*/ true);
723728

724729
print_compile_messages();
@@ -843,11 +848,6 @@ Compile::Compile( ciEnv* ci_env, ciMethod* target, int osr_bci,
843848
if (failing()) return;
844849
NOT_PRODUCT( verify_graph_edges(); )
845850

846-
if (StressLCM || StressGCM || StressIGVN || StressCCP ||
847-
StressIncrementalInlining || StressMacroExpansion) {
848-
initialize_stress_seed(directive);
849-
}
850-
851851
// Now optimize
852852
Optimize();
853853
if (failing()) return;

src/hotspot/share/opto/ifnode.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -840,9 +840,9 @@ bool IfNode::is_dominator_unc(CallStaticJavaNode* dom_unc, CallStaticJavaNode* u
840840
}
841841

842842
// Return projection that leads to an uncommon trap if any
843-
ProjNode* IfNode::uncommon_trap_proj(CallStaticJavaNode*& call) const {
843+
ProjNode* IfNode::uncommon_trap_proj(CallStaticJavaNode*& call, Deoptimization::DeoptReason reason) const {
844844
for (int i = 0; i < 2; i++) {
845-
call = proj_out(i)->is_uncommon_trap_proj();
845+
call = proj_out(i)->is_uncommon_trap_proj(reason);
846846
if (call != nullptr) {
847847
return proj_out(i);
848848
}

src/hotspot/share/opto/parse.hpp

+5
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,11 @@ class Parse : public GraphKit {
612612
// Use speculative type to optimize CmpP node
613613
Node* optimize_cmp_with_klass(Node* c);
614614

615+
// Stress unstable if traps
616+
void stress_trap(IfNode* orig_iff, Node* counter, Node* incr_store);
617+
// Increment counter used by StressUnstableIfTraps
618+
void increment_trap_stress_counter(Node*& counter, Node*& incr_store);
619+
615620
public:
616621
#ifndef PRODUCT
617622
// Handle PrintOpto, etc.

src/hotspot/share/opto/parse2.cpp

+77
Original file line numberDiff line numberDiff line change
@@ -1371,10 +1371,27 @@ inline int Parse::repush_if_args() {
13711371
return bc_depth;
13721372
}
13731373

1374+
// Used by StressUnstableIfTraps
1375+
static volatile int _trap_stress_counter = 0;
1376+
1377+
void Parse::increment_trap_stress_counter(Node*& counter, Node*& incr_store) {
1378+
Node* counter_addr = makecon(TypeRawPtr::make((address)&_trap_stress_counter));
1379+
counter = make_load(control(), counter_addr, TypeInt::INT, T_INT, Compile::AliasIdxRaw, MemNode::unordered);
1380+
counter = _gvn.transform(new AddINode(counter, intcon(1)));
1381+
incr_store = store_to_memory(control(), counter_addr, counter, T_INT, Compile::AliasIdxRaw, MemNode::unordered);
1382+
}
1383+
13741384
//----------------------------------do_ifnull----------------------------------
13751385
void Parse::do_ifnull(BoolTest::mask btest, Node *c) {
13761386
int target_bci = iter().get_dest();
13771387

1388+
Node* counter = nullptr;
1389+
Node* incr_store = nullptr;
1390+
bool do_stress_trap = StressUnstableIfTraps && ((C->random() % 2) == 0);
1391+
if (do_stress_trap) {
1392+
increment_trap_stress_counter(counter, incr_store);
1393+
}
1394+
13781395
Block* branch_block = successor_for_bci(target_bci);
13791396
Block* next_block = successor_for_bci(iter().next_bci());
13801397

@@ -1439,6 +1456,10 @@ void Parse::do_ifnull(BoolTest::mask btest, Node *c) {
14391456
} else { // Path is live.
14401457
adjust_map_after_if(BoolTest(btest).negate(), c, 1.0-prob, next_block);
14411458
}
1459+
1460+
if (do_stress_trap) {
1461+
stress_trap(iff, counter, incr_store);
1462+
}
14421463
}
14431464

14441465
//------------------------------------do_if------------------------------------
@@ -1468,6 +1489,13 @@ void Parse::do_if(BoolTest::mask btest, Node* c) {
14681489
return;
14691490
}
14701491

1492+
Node* counter = nullptr;
1493+
Node* incr_store = nullptr;
1494+
bool do_stress_trap = StressUnstableIfTraps && ((C->random() % 2) == 0);
1495+
if (do_stress_trap) {
1496+
increment_trap_stress_counter(counter, incr_store);
1497+
}
1498+
14711499
// Sanity check the probability value
14721500
assert(0.0f < prob && prob < 1.0f,"Bad probability in Parser");
14731501

@@ -1550,9 +1578,58 @@ void Parse::do_if(BoolTest::mask btest, Node* c) {
15501578
} else {
15511579
adjust_map_after_if(untaken_btest, c, untaken_prob, next_block);
15521580
}
1581+
1582+
if (do_stress_trap) {
1583+
stress_trap(iff, counter, incr_store);
1584+
}
1585+
}
1586+
1587+
// Force unstable if traps to be taken randomly to trigger intermittent bugs such as incorrect debug information.
1588+
// Add another if before the unstable if that checks a "random" condition at runtime (a simple shared counter) and
1589+
// then either takes the trap or executes the original, unstable if.
1590+
void Parse::stress_trap(IfNode* orig_iff, Node* counter, Node* incr_store) {
1591+
// Search for an unstable if trap
1592+
CallStaticJavaNode* trap = nullptr;
1593+
assert(orig_iff->Opcode() == Op_If && orig_iff->outcnt() == 2, "malformed if");
1594+
ProjNode* trap_proj = orig_iff->uncommon_trap_proj(trap, Deoptimization::Reason_unstable_if);
1595+
if (trap == nullptr || !trap->jvms()->should_reexecute()) {
1596+
// No suitable trap found. Remove unused counter load and increment.
1597+
C->gvn_replace_by(incr_store, incr_store->in(MemNode::Memory));
1598+
return;
1599+
}
1600+
1601+
// Remove trap from optimization list since we add another path to the trap.
1602+
bool success = C->remove_unstable_if_trap(trap, true);
1603+
assert(success, "Trap already modified");
1604+
1605+
// Add a check before the original if that will trap with a certain frequency and execute the original if otherwise
1606+
int freq_log = (C->random() % 31) + 1; // Random logarithmic frequency in [1, 31]
1607+
Node* mask = intcon(right_n_bits(freq_log));
1608+
counter = _gvn.transform(new AndINode(counter, mask));
1609+
Node* cmp = _gvn.transform(new CmpINode(counter, intcon(0)));
1610+
Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::mask::eq));
1611+
IfNode* iff = _gvn.transform(new IfNode(orig_iff->in(0), bol, orig_iff->_prob, orig_iff->_fcnt))->as_If();
1612+
Node* if_true = _gvn.transform(new IfTrueNode(iff));
1613+
Node* if_false = _gvn.transform(new IfFalseNode(iff));
1614+
assert(!if_true->is_top() && !if_false->is_top(), "trap always / never taken");
1615+
1616+
// Trap
1617+
assert(trap_proj->outcnt() == 1, "some other nodes are dependent on the trap projection");
1618+
1619+
Node* trap_region = new RegionNode(3);
1620+
trap_region->set_req(1, trap_proj);
1621+
trap_region->set_req(2, if_true);
1622+
trap->set_req(0, _gvn.transform(trap_region));
1623+
1624+
// Don't trap, execute original if
1625+
orig_iff->set_req(0, if_false);
15531626
}
15541627

15551628
bool Parse::path_is_suitable_for_uncommon_trap(float prob) const {
1629+
// Randomly skip emitting an uncommon trap
1630+
if (StressUnstableIfTraps && ((C->random() % 2) == 0)) {
1631+
return false;
1632+
}
15561633
// Don't want to speculate on uncommon traps when running with -Xcomp
15571634
if (!UseInterpreter) {
15581635
return false;

test/hotspot/jtreg/compiler/arguments/TestStressOptions.java

+9-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
/*
2525
* @test
2626
* @key stress randomness
27-
* @bug 8252219 8256535 8317349
27+
* @bug 8252219 8256535 8317349 8319879 8335334
2828
* @requires vm.compiler2.enabled
2929
* @summary Tests that different combinations of stress options and
3030
* -XX:StressSeed=N are accepted.
@@ -48,6 +48,14 @@
4848
* compiler.arguments.TestStressOptions
4949
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+StressMacroExpansion -XX:StressSeed=42
5050
* compiler.arguments.TestStressOptions
51+
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+StressIncrementalInlining
52+
* compiler.arguments.TestStressOptions
53+
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+StressIncrementalInlining -XX:StressSeed=42
54+
* compiler.arguments.TestStressOptions
55+
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+StressUnstableIfTraps
56+
* compiler.arguments.TestStressOptions
57+
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+StressUnstableIfTraps -XX:StressSeed=42
58+
* compiler.arguments.TestStressOptions
5159
*/
5260

5361
package compiler.arguments;

test/hotspot/jtreg/compiler/c2/irTests/TestPrunedExHandler.java

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
* @test
3030
* @bug 8267532
3131
* @summary check that uncommon trap is generated for unhandled catch block
32+
* @requires vm.opt.StressUnstableIfTraps == null | !vm.opt.StressUnstableIfTraps
3233
* @library /test/lib /
3334
* @requires vm.opt.DeoptimizeALot != true
3435
* @run driver compiler.c2.irTests.TestPrunedExHandler

test/hotspot/jtreg/compiler/cha/StrengthReduceInterfaceCall.java

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
/*
2525
* @test
2626
* @requires !vm.graal.enabled
27+
* @requires vm.opt.StressUnstableIfTraps == null | !vm.opt.StressUnstableIfTraps
2728
* @modules java.base/jdk.internal.org.objectweb.asm
2829
* java.base/jdk.internal.misc
2930
* java.base/jdk.internal.vm.annotation

test/hotspot/jtreg/compiler/jvmci/compilerToVM/MaterializeVirtualObjectTest.java

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
*
2828
* @requires vm.jvmci & vm.compMode == "Xmixed"
2929
* @requires vm.opt.final.EliminateAllocations == true
30+
* @requires vm.opt.StressUnstableIfTraps == null | !vm.opt.StressUnstableIfTraps
3031
*
3132
* @comment no "-Xcomp -XX:-TieredCompilation" combination allowed until JDK-8140018 is resolved
3233
* @requires vm.opt.TieredCompilation == null | vm.opt.TieredCompilation == true

test/hotspot/jtreg/compiler/rangechecks/TestExplicitRangeChecks.java

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
* @test
2626
* @bug 8073480
2727
* @summary explicit range checks should be recognized by C2
28+
* @requires vm.opt.StressUnstableIfTraps == null | !vm.opt.StressUnstableIfTraps
2829
* @library /test/lib /
2930
* @modules java.base/jdk.internal.misc:+open
3031
* @build jdk.test.whitebox.WhiteBox

test/hotspot/jtreg/compiler/uncommontrap/TestUnstableIfTrap.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
/*
2525
* @test
2626
* @bug 8030976 8059226
27-
* @requires !vm.graal.enabled
27+
* @requires !vm.graal.enabled & (vm.opt.StressUnstableIfTraps == null | !vm.opt.StressUnstableIfTraps)
2828
* @library /test/lib /
2929
* @modules java.base/jdk.internal.org.objectweb.asm
3030
* java.base/jdk.internal.misc

test/hotspot/jtreg/compiler/vectorization/runner/BasicBooleanOpTest.java

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
/*
2626
* @test
2727
* @summary Vectorization test on basic boolean operations
28+
* @requires vm.opt.StressUnstableIfTraps == null | !vm.opt.StressUnstableIfTraps
2829
* @library /test/lib /
2930
*
3031
* @build jdk.test.whitebox.WhiteBox

test/hotspot/jtreg/compiler/whitebox/DeoptimizeFramesTest.java

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
* @test DeoptimizeFramesTest
2626
* @bug 8028595
2727
* @summary testing of WB::deoptimizeFrames()
28+
* @requires vm.opt.StressUnstableIfTraps == null | !vm.opt.StressUnstableIfTraps
2829
* @library /test/lib /
2930
* @modules java.base/jdk.internal.misc
3031
* java.management

test/jdk/jdk/jfr/event/compiler/TestDeoptimization.java

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ public static void dummyMethod(boolean b) {
5353
* @requires vm.hasJFR
5454
* @requires vm.compMode != "Xint"
5555
* @requires vm.flavor == "server" & (vm.opt.TieredStopAtLevel == 4 | vm.opt.TieredStopAtLevel == null)
56+
* @requires vm.opt.StressUnstableIfTraps == null | !vm.opt.StressUnstableIfTraps
5657
* @library /test/lib
5758
* @build jdk.test.whitebox.WhiteBox
5859
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox

0 commit comments

Comments
 (0)