changeset 16590:c62c1e0060cc

Don't allow infinite loops to explode loop frequencies
author Tom Rodriguez <tom.rodriguez@oracle.com>
date Wed, 23 Jul 2014 17:36:15 -0700
parents 6bdd2ec553eb
children 86eee6794713
files graal/com.oracle.graal.java/src/com/oracle/graal/java/ComputeLoopFrequenciesClosure.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/FixedNodeProbabilityCache.java graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java
diffstat 4 files changed, 22 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/ComputeLoopFrequenciesClosure.java	Wed Jul 23 15:01:58 2014 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/ComputeLoopFrequenciesClosure.java	Wed Jul 23 17:36:15 2014 -0700
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.java;
 
+import static com.oracle.graal.nodes.cfg.ControlFlowGraph.*;
+
 import java.util.*;
 import java.util.stream.*;
 
@@ -30,7 +32,6 @@
 
 public class ComputeLoopFrequenciesClosure extends ReentrantNodeIterator.NodeIteratorClosure<Double> {
 
-    private static final double EPSILON = Double.MIN_NORMAL;
     private static final ComputeLoopFrequenciesClosure INSTANCE = new ComputeLoopFrequenciesClosure();
 
     private ComputeLoopFrequenciesClosure() {
@@ -62,8 +63,8 @@
 
         double exitProbability = exitStates.values().stream().mapToDouble(d -> d).sum();
         assert exitProbability <= 1D && exitProbability >= 0D;
-        if (exitProbability < EPSILON) {
-            exitProbability = EPSILON;
+        if (exitProbability < MIN_PROBABILITY) {
+            exitProbability = MIN_PROBABILITY;
         }
         double loopFrequency = 1D / exitProbability;
         loop.setLoopFrequency(loopFrequency);
@@ -75,14 +76,14 @@
     }
 
     /**
-     * Multiplies a and b and saturates the result to 1/{@link Double#MIN_NORMAL}.
+     * Multiplies a and b and saturates the result to 1/{@link #MIN_PROBABILITY}.
      *
-     * @return a times b saturated to 1/{@link Double#MIN_NORMAL}
+     * @return a times b saturated to 1/{@link #MIN_PROBABILITY}
      */
     public static double multiplySaturate(double a, double b) {
         double r = a * b;
-        if (r > 1 / Double.MIN_NORMAL) {
-            return 1 / Double.MIN_NORMAL;
+        if (r > 1 / MIN_PROBABILITY) {
+            return 1 / MIN_PROBABILITY;
         }
         return r;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java	Wed Jul 23 15:01:58 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java	Wed Jul 23 17:36:15 2014 -0700
@@ -31,6 +31,12 @@
 import com.oracle.graal.nodes.*;
 
 public class ControlFlowGraph implements AbstractControlFlowGraph<Block> {
+    /**
+     * Don't allow probability values to be become too small as this makes frequency calculations
+     * large enough that they can overflow the range of a double. This commonly happens with
+     * infinite loops within infinite loops.
+     */
+    public static final double MIN_PROBABILITY = 0.000001;
 
     public final StructuredGraph graph;
 
@@ -221,8 +227,8 @@
                     }
                 }
             }
-            if (probability > 1. / Double.MIN_NORMAL) {
-                probability = 1. / Double.MIN_NORMAL;
+            if (probability > 1. / MIN_PROBABILITY) {
+                probability = 1. / MIN_PROBABILITY;
             }
             block.setPredecessors(predecessors);
             block.setProbability(probability);
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/FixedNodeProbabilityCache.java	Wed Jul 23 15:01:58 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/FixedNodeProbabilityCache.java	Wed Jul 23 17:36:15 2014 -0700
@@ -114,6 +114,7 @@
             ControlSplitNode split = (ControlSplitNode) current.predecessor();
             probability = split.probability((BeginNode) current) * applyAsDouble(split);
         }
+        assert !Double.isNaN(probability) && !Double.isInfinite(probability) : current + " " + probability;
         cache.put(current, probability);
         return probability;
     }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java	Wed Jul 23 15:01:58 2014 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java	Wed Jul 23 17:36:15 2014 -0700
@@ -410,7 +410,11 @@
             NodeClass nodeClass = node.getNodeClass();
             node.getDebugProperties(props);
             if (probabilities != null && node instanceof FixedNode) {
-                props.put("probability", probabilities.applyAsDouble((FixedNode) node));
+                try {
+                    props.put("probability", probabilities.applyAsDouble((FixedNode) node));
+                } catch (Throwable t) {
+                    props.put("probability", t);
+                }
             }
             writeInt(getNodeId(node));
             writePoolObject(nodeClass);