8033260: assert(lrg._area >= 0.0) failed: negative spill area
Summary: Change type from float to double on block frequency, and add check for +Inf - +Inf operation
Reviewed-by: kvn, roland
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/Block.java Tue Feb 25 14:09:02 2014 +0100
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/Block.java Tue Feb 25 17:51:27 2014 +0100
@@ -48,7 +48,7 @@
preOrderField = new CIntField(type.getCIntegerField("_pre_order"), 0);
domDepthField = new CIntField(type.getCIntegerField("_dom_depth"), 0);
idomField = type.getAddressField("_idom");
- freqField = type.getJFloatField("_freq");
+ freqField = type.getJDoubleField("_freq");
}
private static AddressField nodesField;
@@ -57,7 +57,7 @@
private static CIntField preOrderField;
private static CIntField domDepthField;
private static AddressField idomField;
- private static JFloatField freqField;
+ private static JDoubleField freqField;
public Block(Address addr) {
super(addr);
@@ -67,8 +67,8 @@
return (int)preOrderField.getValue(getAddress());
}
- public float freq() {
- return (float)freqField.getValue(getAddress());
+ public double freq() {
+ return (double)freqField.getValue(getAddress());
}
public Node_List nodes() {
--- a/hotspot/src/share/vm/opto/block.hpp Tue Feb 25 14:09:02 2014 +0100
+++ b/hotspot/src/share/vm/opto/block.hpp Tue Feb 25 17:51:27 2014 +0100
@@ -90,9 +90,9 @@
class CFGElement : public ResourceObj {
friend class VMStructs;
public:
- float _freq; // Execution frequency (estimate)
+ double _freq; // Execution frequency (estimate)
- CFGElement() : _freq(0.0f) {}
+ CFGElement() : _freq(0.0) {}
virtual bool is_block() { return false; }
virtual bool is_loop() { return false; }
Block* as_Block() { assert(is_block(), "must be block"); return (Block*)this; }
@@ -202,7 +202,7 @@
// BLOCK_FREQUENCY is a sentinel to mark uses of constant block frequencies.
// It is currently also used to scale such frequencies relative to
// FreqCountInvocations relative to the old value of 1500.
-#define BLOCK_FREQUENCY(f) ((f * (float) 1500) / FreqCountInvocations)
+#define BLOCK_FREQUENCY(f) ((f * (double) 1500) / FreqCountInvocations)
// Register Pressure (estimate) for Splitting heuristic
uint _reg_pressure;
@@ -393,7 +393,7 @@
CFGLoop* _root_loop;
// Outmost loop frequency
- float _outer_loop_frequency;
+ double _outer_loop_frequency;
// Per node latency estimation, valid only during GCM
GrowableArray<uint>* _node_latency;
@@ -508,7 +508,7 @@
}
// Get the outer most frequency
- float get_outer_loop_frequency() const {
+ double get_outer_loop_frequency() const {
return _outer_loop_frequency;
}
@@ -656,13 +656,13 @@
class BlockProbPair VALUE_OBJ_CLASS_SPEC {
protected:
Block* _target; // block target
- float _prob; // probability of edge to block
+ double _prob; // probability of edge to block
public:
BlockProbPair() : _target(NULL), _prob(0.0) {}
- BlockProbPair(Block* b, float p) : _target(b), _prob(p) {}
+ BlockProbPair(Block* b, double p) : _target(b), _prob(p) {}
Block* get_target() const { return _target; }
- float get_prob() const { return _prob; }
+ double get_prob() const { return _prob; }
};
//------------------------------CFGLoop-------------------------------------------
@@ -675,8 +675,8 @@
CFGLoop *_child; // first child, use child's sibling to visit all immediately nested loops
GrowableArray<CFGElement*> _members; // list of members of loop
GrowableArray<BlockProbPair> _exits; // list of successor blocks and their probabilities
- float _exit_prob; // probability any loop exit is taken on a single loop iteration
- void update_succ_freq(Block* b, float freq);
+ double _exit_prob; // probability any loop exit is taken on a single loop iteration
+ void update_succ_freq(Block* b, double freq);
public:
CFGLoop(int id) :
@@ -702,9 +702,9 @@
void compute_loop_depth(int depth);
void compute_freq(); // compute frequency with loop assuming head freq 1.0f
void scale_freq(); // scale frequency by loop trip count (including outer loops)
- float outer_loop_freq() const; // frequency of outer loop
+ double outer_loop_freq() const; // frequency of outer loop
bool in_loop_nest(Block* b);
- float trip_count() const { return 1.0f / _exit_prob; }
+ double trip_count() const { return 1.0 / _exit_prob; }
virtual bool is_loop() { return true; }
int id() { return _id; }
@@ -723,7 +723,7 @@
private:
Block * _from; // Source basic block
Block * _to; // Destination basic block
- float _freq; // Execution frequency (estimate)
+ double _freq; // Execution frequency (estimate)
int _state;
bool _infrequent;
int _from_pct;
@@ -742,13 +742,13 @@
interior // edge is interior to trace (could be backedge)
};
- CFGEdge(Block *from, Block *to, float freq, int from_pct, int to_pct) :
+ CFGEdge(Block *from, Block *to, double freq, int from_pct, int to_pct) :
_from(from), _to(to), _freq(freq),
_from_pct(from_pct), _to_pct(to_pct), _state(open) {
_infrequent = from_infrequent() || to_infrequent();
}
- float freq() const { return _freq; }
+ double freq() const { return _freq; }
Block* from() const { return _from; }
Block* to () const { return _to; }
int infrequent() const { return _infrequent; }
--- a/hotspot/src/share/vm/opto/chaitin.cpp Tue Feb 25 14:09:02 2014 +0100
+++ b/hotspot/src/share/vm/opto/chaitin.cpp Tue Feb 25 17:51:27 2014 +0100
@@ -210,7 +210,7 @@
{
NOT_PRODUCT( Compile::TracePhase t3("ctorChaitin", &_t_ctorChaitin, TimeCompiler); )
- _high_frequency_lrg = MIN2(float(OPTO_LRG_HIGH_FREQ), _cfg.get_outer_loop_frequency());
+ _high_frequency_lrg = MIN2(double(OPTO_LRG_HIGH_FREQ), _cfg.get_outer_loop_frequency());
// Build a list of basic blocks, sorted by frequency
_blks = NEW_RESOURCE_ARRAY(Block *, _cfg.number_of_blocks());
--- a/hotspot/src/share/vm/opto/gcm.cpp Tue Feb 25 14:09:02 2014 +0100
+++ b/hotspot/src/share/vm/opto/gcm.cpp Tue Feb 25 17:51:27 2014 +0100
@@ -1661,10 +1661,10 @@
}
assert (_members.length() > 0, "no empty loops");
Block* hd = head();
- hd->_freq = 1.0f;
+ hd->_freq = 1.0;
for (int i = 0; i < _members.length(); i++) {
CFGElement* s = _members.at(i);
- float freq = s->_freq;
+ double freq = s->_freq;
if (s->is_block()) {
Block* b = s->as_Block();
for (uint j = 0; j < b->_num_succs; j++) {
@@ -1676,7 +1676,7 @@
assert(lp->_parent == this, "immediate child");
for (int k = 0; k < lp->_exits.length(); k++) {
Block* eb = lp->_exits.at(k).get_target();
- float prob = lp->_exits.at(k).get_prob();
+ double prob = lp->_exits.at(k).get_prob();
update_succ_freq(eb, freq * prob);
}
}
@@ -1688,7 +1688,7 @@
// inner blocks do not get erroneously scaled.
if (_depth != 0) {
// Total the exit probabilities for this loop.
- float exits_sum = 0.0f;
+ double exits_sum = 0.0f;
for (int i = 0; i < _exits.length(); i++) {
exits_sum += _exits.at(i).get_prob();
}
@@ -1935,7 +1935,7 @@
//------------------------------update_succ_freq-------------------------------
// Update the appropriate frequency associated with block 'b', a successor of
// a block in this loop.
-void CFGLoop::update_succ_freq(Block* b, float freq) {
+void CFGLoop::update_succ_freq(Block* b, double freq) {
if (b->_loop == this) {
if (b == head()) {
// back branch within the loop
@@ -1976,11 +1976,11 @@
// Scale frequency of loops and blocks by trip counts from outer loops
// Do a top down traversal of loop tree (visit outer loops first.)
void CFGLoop::scale_freq() {
- float loop_freq = _freq * trip_count();
+ double loop_freq = _freq * trip_count();
_freq = loop_freq;
for (int i = 0; i < _members.length(); i++) {
CFGElement* s = _members.at(i);
- float block_freq = s->_freq * loop_freq;
+ double block_freq = s->_freq * loop_freq;
if (g_isnan(block_freq) || block_freq < MIN_BLOCK_FREQUENCY)
block_freq = MIN_BLOCK_FREQUENCY;
s->_freq = block_freq;
@@ -1993,7 +1993,7 @@
}
// Frequency of outer loop
-float CFGLoop::outer_loop_freq() const {
+double CFGLoop::outer_loop_freq() const {
if (_child != NULL) {
return _child->_freq;
}
@@ -2042,7 +2042,7 @@
k = 0;
}
Block *blk = _exits.at(i).get_target();
- float prob = _exits.at(i).get_prob();
+ double prob = _exits.at(i).get_prob();
tty->print(" ->%d@%d%%", blk->_pre_order, (int)(prob*100));
}
tty->print("\n");
--- a/hotspot/src/share/vm/opto/ifg.cpp Tue Feb 25 14:09:02 2014 +0100
+++ b/hotspot/src/share/vm/opto/ifg.cpp Tue Feb 25 17:51:27 2014 +0100
@@ -693,7 +693,7 @@
assert(int_pressure.current_pressure() == count_int_pressure(liveout), "the int pressure is incorrect");
assert(float_pressure.current_pressure() == count_float_pressure(liveout), "the float pressure is incorrect");
}
- assert(!(lrg._area < 0.0), "negative spill area" );
+ assert(lrg._area >= 0.0, "negative spill area" );
}
}
@@ -762,7 +762,7 @@
int inst_count = last_inst - first_inst;
double cost = (inst_count <= 0) ? 0.0 : block->_freq * double(inst_count);
- assert(!(cost < 0.0), "negative spill cost" );
+ assert(cost >= 0.0, "negative spill cost" );
compute_initial_block_pressure(block, &liveout, int_pressure, float_pressure, cost);
@@ -789,7 +789,11 @@
}
} else {
// A live range ends at its definition, remove the remaining area.
- lrg._area -= cost;
+ // If the cost is +Inf (which might happen in extreme cases), the lrg area will also be +Inf,
+ // and +Inf - +Inf = NaN. So let's not do that subtraction.
+ if (g_isfinite(cost)) {
+ lrg._area -= cost;
+ }
assert(lrg._area >= 0.0, "negative spill area" );
assign_high_score_to_immediate_copies(block, n, lrg, location + 1, last_inst);
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Tue Feb 25 14:09:02 2014 +0100
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Tue Feb 25 17:51:27 2014 +0100
@@ -1176,9 +1176,9 @@
c2_nonstatic_field(Block, _pre_order, uint) \
c2_nonstatic_field(Block, _dom_depth, uint) \
c2_nonstatic_field(Block, _idom, Block*) \
- c2_nonstatic_field(Block, _freq, jfloat) \
+ c2_nonstatic_field(Block, _freq, jdouble) \
\
- c2_nonstatic_field(CFGElement, _freq, jfloat) \
+ c2_nonstatic_field(CFGElement, _freq, jdouble) \
\
c2_nonstatic_field(Block_List, _cnt, uint) \
\