[RFR] 8217359: C2 compiler triggers SIGSEGV after tranformation in ConvI2LNode::Ideal
Yangfei (Felix)
felix.yang at huawei.com
Fri Jan 18 05:36:11 UTC 2019
Hi,
Can someone help review this change to the C2 compiler?
Bug: https://bugs.openjdk.java.net/browse/JDK-8217359
Webrev: http://cr.openjdk.java.net/~fyang/8217359/webrev.00/
The bug triggers when C2 compiler does the following transformation in function ConvI2LNode::Ideal:
// Convert ConvI2L(AddI(x, y)) to AddL(ConvI2L(x), ConvI2L(y))
......
395 Node* cx = phase->C->constrained_convI2L(phase, x, TypeInt::make(rxlo, rxhi, widen), NULL);
396 Node* cy = phase->C->constrained_convI2L(phase, y, TypeInt::make(rylo, ryhi, widen), NULL);
....
Here is the process of how it triggers:
// =========================================================
// Before line 395, x is an AddINode (id: 202). y is also an AddINode (id: 553) and x is a subtree of y.
// The ideal graph looks like:
//
// ... ... ... ...
// \ | / |
// 86_Phi 33_ConI
// | /
// \ | /
// 202_AddI
//
// ... ... ... ...
// | \ | /
// 27_ConI 202_AddI --------- (node x)
// | /
// \ | /
// 549_SubI
// | ...
// \ | /
// 553_AddI ---------- (node y)
//
// ==========================================================
// After line 395, x is converted to cx and cx is an AddLNode (id: 1274).
// At this point, everything looks fine.
// ... ... ...
// \ / /
// 1271_ConvI2L 1273_ConL
// | /
// \ | /
// 1274_AddL
//
// ==========================================================
// In line 396, y will be converted to cy. In this progress, y
// and its subnode will all be converted recursively. This is
// a rather long progress. The convertion of y is like this:
//
// Node 27_ConI will be converted to node 1278_ConL.
//
// Since x(202) is the input edge of node 549, it will be
// converted again. And the result cx_2 is node 1282_AddL.
// The structure of cx_2 is the same as cx. After GVN(hash_find_insert()),
// 1282_AddL is replaced with 1274_AddL.
//
// Then 549_SubI will be converted to 1283_SubL and the ideal graph looks like:
// ... ... ...
// \ / /
// 1271_ConvI2L 1273_ConL
// ... | /
// | \ | /
// 1278_ConL 1274_AddL
// | /
// \ | /
// 1283_SubL
//
// After that, C2 will do the following transformation to node 1283_SubL:
// x - (y + cons) ==> (x - y) - cons
//
// When this is done, node 1283_SubL is converted to node 1286_AddL:
// ... ... ...
// | | /
// 1278_ConL 1271_ConI2L
// | / ...
// \ | / /
// 1284_SubL 1285_ConL
// | /
// \ | /
// 1286_AddL
//
// Then in function subsume_node(), 1283_SubL is replaced with 1286_AddL.
// During this progress, following operations will be carried out:
// | In function subsume_node(), 1283_SubL will be regarded as a
// | dead_node since it is replaced by 1286_AddL. The same inspection
// | of dead node will be carried out to the subnodes of 1283
// | recursively. And remove_dead_node() function will be called
// | by subsume_node() to replace the input edges of dead node to NULL.
// | 1274_AddL is node cx. At this moment, 1274_AddL has only one
// | output edge, that is 1283. Since 1283 is a dead node, 1274 will
// | also be regarded as a dead node. Then input edges of 1274_AddL
// | will be set to NULL. After that, cx will be an isolated node which
// | has neither input edge nor output edge.
//
// ==========================================
// After all of this, program continues and cx->in(2) is used in addnode.cpp:163.
// Since now cx has no input edges, the program crashes.
The proposed solution is fairly straight-forward:
After the conversion of x, build a hook node add a use to cx to prevent it from dying.
When conversion of y is finished, this new output of cx is removed.
JTreg tested with both x86_64 fastdebug & release build. Is it OK?
Thanks,
Felix
More information about the hotspot-compiler-dev
mailing list