1 /* |
1 /* |
2 * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
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 |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. |
7 * published by the Free Software Foundation. |
43 import org.graalvm.compiler.nodes.DynamicDeoptimizeNode; |
43 import org.graalvm.compiler.nodes.DynamicDeoptimizeNode; |
44 import org.graalvm.compiler.nodes.EndNode; |
44 import org.graalvm.compiler.nodes.EndNode; |
45 import org.graalvm.compiler.nodes.FixedNode; |
45 import org.graalvm.compiler.nodes.FixedNode; |
46 import org.graalvm.compiler.nodes.IfNode; |
46 import org.graalvm.compiler.nodes.IfNode; |
47 import org.graalvm.compiler.nodes.LogicNode; |
47 import org.graalvm.compiler.nodes.LogicNode; |
|
48 import org.graalvm.compiler.nodes.LoopExitNode; |
48 import org.graalvm.compiler.nodes.StructuredGraph; |
49 import org.graalvm.compiler.nodes.StructuredGraph; |
49 import org.graalvm.compiler.nodes.ValueNode; |
50 import org.graalvm.compiler.nodes.ValueNode; |
50 import org.graalvm.compiler.nodes.ValuePhiNode; |
51 import org.graalvm.compiler.nodes.ValuePhiNode; |
51 import org.graalvm.compiler.nodes.calc.IsNullNode; |
52 import org.graalvm.compiler.nodes.calc.IsNullNode; |
52 import org.graalvm.compiler.nodes.extended.NullCheckNode; |
53 import org.graalvm.compiler.nodes.extended.NullCheckNode; |
163 } |
164 } |
164 } |
165 } |
165 |
166 |
166 private static void tryUseTrappingNullCheck(AbstractDeoptimizeNode deopt, Node predecessor, DeoptimizationReason deoptimizationReason, Speculation speculation, long implicitNullCheckLimit) { |
167 private static void tryUseTrappingNullCheck(AbstractDeoptimizeNode deopt, Node predecessor, DeoptimizationReason deoptimizationReason, Speculation speculation, long implicitNullCheckLimit) { |
167 assert predecessor != null; |
168 assert predecessor != null; |
168 if (deoptimizationReason != DeoptimizationReason.NullCheckException && deoptimizationReason != DeoptimizationReason.UnreachedCode) { |
169 if (deoptimizationReason != DeoptimizationReason.NullCheckException && deoptimizationReason != DeoptimizationReason.UnreachedCode && |
|
170 deoptimizationReason != DeoptimizationReason.TypeCheckedInliningViolated) { |
169 deopt.getDebug().log(DebugContext.INFO_LEVEL, "Not a null check or unreached %s", predecessor); |
171 deopt.getDebug().log(DebugContext.INFO_LEVEL, "Not a null check or unreached %s", predecessor); |
170 return; |
172 return; |
171 } |
173 } |
172 assert speculation != null; |
174 assert speculation != null; |
173 if (!speculation.equals(SpeculationLog.NO_SPECULATION)) { |
175 if (!speculation.equals(SpeculationLog.NO_SPECULATION)) { |
174 deopt.getDebug().log(DebugContext.INFO_LEVEL, "Has a speculation %s", predecessor); |
176 deopt.getDebug().log(DebugContext.INFO_LEVEL, "Has a speculation %s", predecessor); |
175 return; |
177 return; |
176 } |
178 } |
177 if (predecessor instanceof AbstractMergeNode) { |
179 |
178 AbstractMergeNode merge = (AbstractMergeNode) predecessor; |
180 // Skip over loop exit nodes. |
|
181 Node pred = predecessor; |
|
182 while (pred instanceof LoopExitNode) { |
|
183 pred = pred.predecessor(); |
|
184 } |
|
185 if (pred instanceof AbstractMergeNode) { |
|
186 AbstractMergeNode merge = (AbstractMergeNode) pred; |
179 if (merge.phis().isEmpty()) { |
187 if (merge.phis().isEmpty()) { |
180 for (AbstractEndNode end : merge.cfgPredecessors().snapshot()) { |
188 for (AbstractEndNode end : merge.cfgPredecessors().snapshot()) { |
181 checkPredecessor(deopt, end.predecessor(), deoptimizationReason, implicitNullCheckLimit); |
189 checkPredecessor(deopt, end.predecessor(), deoptimizationReason, implicitNullCheckLimit); |
182 } |
190 } |
183 } |
191 } |
184 } else if (predecessor instanceof AbstractBeginNode) { |
192 } else if (pred instanceof AbstractBeginNode) { |
185 checkPredecessor(deopt, predecessor, deoptimizationReason, implicitNullCheckLimit); |
193 checkPredecessor(deopt, pred, deoptimizationReason, implicitNullCheckLimit); |
186 } else { |
194 } else { |
187 deopt.getDebug().log(DebugContext.INFO_LEVEL, "Not a Begin or Merge %s", predecessor); |
195 deopt.getDebug().log(DebugContext.INFO_LEVEL, "Not a Begin or Merge %s", pred); |
188 } |
196 } |
189 } |
197 } |
190 |
198 |
191 private static void checkPredecessor(AbstractDeoptimizeNode deopt, Node predecessor, DeoptimizationReason deoptimizationReason, long implicitNullCheckLimit) { |
199 private static void checkPredecessor(AbstractDeoptimizeNode deopt, Node predecessor, DeoptimizationReason deoptimizationReason, long implicitNullCheckLimit) { |
192 Node current = predecessor; |
200 Node current = predecessor; |