RFR: 8286182: C2: crash with SIGFPE when executing compiled code

Martin Doerr mdoerr at openjdk.java.net
Wed May 18 12:40:58 UTC 2022


On Mon, 16 May 2022 12:36:43 GMT, Martin Doerr <mdoerr at openjdk.org> wrote:

> The bug is not assigned to me, but I have seen that the C2 code which checks for div by 0 is not aware of the new nodes from [JDK-8284742](https://bugs.openjdk.java.net/browse/JDK-8284742).
> This fixes the VM to pass the reproducer. I'm not sure if more opcode checks are required to get added.

While evaluation is ongoing I have thought a bit about making the div node dependent on a single check which avoids all SIGFPE cases:

diff --git a/src/hotspot/share/opto/parse3.cpp b/src/hotspot/share/opto/parse3.cpp
index 7e0f854436b..9d4226571ae 100644
--- a/src/hotspot/share/opto/parse3.cpp
+++ b/src/hotspot/share/opto/parse3.cpp
@@ -484,26 +484,30 @@ void Parse::do_divmod_fixup() {
     return;
   }
 
-  // The generated graph is equivalent to (in2 == -1) ? -in1 : (in1 / in2)
-  // we need to have a separate branch for in2 == -1 due to the special
-  // case of min_jint / -1
-  Node* cmp = _gvn.transform(CmpNode::make(in2, _gvn.integercon(-1, bt), bt));
-  Node* bol = Bool(cmp, BoolTest::eq);
-  IfNode* iff = create_and_map_if(control(), bol, PROB_UNLIKELY_MAG(3), COUNT_UNKNOWN);
+  // Check if in2 < -1 or > 1 by one CmpUNode (in2 + 1 >u 1). Reason:
+  // Div node will have to get pinned, but we can only pin to one region.
+  Node* inc = _gvn.transform(AddNode::make(in2, _gvn.integercon(1, bt), bt));
+  Node* cmp = _gvn.transform(CmpUNode::make(inc, _gvn.integercon(1, bt), bt));
+
+  Node* bol = Bool(cmp, BoolTest::gt);
+  IfNode* iff = create_and_map_if(control(), bol, PROB_MAX, COUNT_UNKNOWN);
   Node* iff_true = IfTrue(iff);
   Node* iff_false = IfFalse(iff);
+
+  Node* res_slow = generate_division(_gvn, iff_true, in1, in2, bc);
+
   Node* res_fast = (bc == Bytecodes::_idiv || bc == Bytecodes::_ldiv)
                    ? _gvn.transform(SubNode::make(_gvn.zerocon(bt), in1, bt))
                    : _gvn.zerocon(bt);
-  Node* res_slow = generate_division(_gvn, iff_false, in1, in2, bc);
+
   Node* merge = new RegionNode(3);
   merge->init_req(1, iff_true);
   merge->init_req(2, iff_false);
   record_for_igvn(merge);
   set_control(_gvn.transform(merge));
   Node* res = new PhiNode(merge, Type::get_const_basic_type(bt));
-  res->init_req(1, res_fast);
-  res->init_req(2, res_slow);
+  res->init_req(1, res_slow);
+  res->init_req(2, res_fast);
   res = _gvn.transform(res);
   push_result(*this, res, bt);
 }

This effectively disables implicit div by 0 checks, but I believe they could get repaired. Are there any opinions about this idea?

-------------

PR: https://git.openjdk.java.net/jdk/pull/8726


More information about the hotspot-compiler-dev mailing list