@Override protected boolean checkMidTierGraph(StructuredGraph graph) { int count = 0; for (IsNullNode isNull : graph.getNodes().filter(IsNullNode.class).snapshot()) { ValueNode value = isNull.getValue(); if (value instanceof CompressionNode) { count++; isNull.replaceFirstInput(value, ((CompressionNode) value).getValue()); } } Assert.assertEquals("graph should contain exactly one IsNullNode", 1, count); return super.checkMidTierGraph(graph); }
/** * In case the scrutinee: * * <ul> * <li>is known to be null, an unconditional deopt is added. * <li>is known to be non-null, the NullCheckNode is removed. * <li>otherwise, the NullCheckNode is lowered to a FixedGuardNode which then allows using it as * anchor for state-tracking. * </ul> * * <p>Precondition: the input (ie, object) hasn't been deverbosified yet. */ private void visitNullCheckNode(NullCheckNode ncn) { ValueNode object = ncn.getObject(); if (state.isNull(object)) { postponedDeopts.addDeoptBefore(ncn, NullCheckException); state.impossiblePath(); return; } if (state.isNonNull(object)) { /* * Redundant NullCheckNode. Unlike GuardingPiNode or FixedGuardNode, NullCheckNode-s * aren't used as GuardingNode-s, thus in this case can be removed without further ado. */ assert FlowUtil.lacksUsages(ncn); graph.removeFixed(ncn); return; } /* * Lower the NullCheckNode to a FixedGuardNode which then allows using it as anchor for * state-tracking. TODO the assumption here is that the code emitted for the resulting * FixedGuardNode is as efficient as for NullCheckNode. */ IsNullNode isNN = graph.unique(IsNullNode.create(object)); reasoner.added.add(isNN); FixedGuardNode nullCheck = graph.add(FixedGuardNode.create(isNN, UnreachedCode, InvalidateReprofile, true)); graph.replaceFixedWithFixed(ncn, nullCheck); state.trackNN(object, nullCheck); }