提交 571459e9 编写于 作者: K kvn

6684714: Optimize EA Connection Graph build performance

Summary: switch on EA by default, optimize Connection Graph construction
Reviewed-by: rasbold, never
上级 cb80591f
...@@ -188,10 +188,6 @@ void OopMap::set_derived_oop(VMReg reg, VMReg derived_from_local_register ) { ...@@ -188,10 +188,6 @@ void OopMap::set_derived_oop(VMReg reg, VMReg derived_from_local_register ) {
} }
} }
void OopMap::set_stack_obj(VMReg reg) {
set_xxx(reg, OopMapValue::stack_obj, VMRegImpl::Bad());
}
// OopMapSet // OopMapSet
OopMapSet::OopMapSet() { OopMapSet::OopMapSet() {
...@@ -399,8 +395,7 @@ void OopMapSet::all_do(const frame *fr, const RegisterMap *reg_map, ...@@ -399,8 +395,7 @@ void OopMapSet::all_do(const frame *fr, const RegisterMap *reg_map,
if ( loc != NULL ) { if ( loc != NULL ) {
if ( omv.type() == OopMapValue::oop_value ) { if ( omv.type() == OopMapValue::oop_value ) {
#ifdef ASSERT #ifdef ASSERT
if (COMPILER2_PRESENT(!DoEscapeAnalysis &&) if ((((uintptr_t)loc & (sizeof(*loc)-1)) != 0) ||
(((uintptr_t)loc & (sizeof(*loc)-1)) != 0) ||
!Universe::heap()->is_in_or_null(*loc)) { !Universe::heap()->is_in_or_null(*loc)) {
tty->print_cr("# Found non oop pointer. Dumping state at failure"); tty->print_cr("# Found non oop pointer. Dumping state at failure");
// try to dump out some helpful debugging information // try to dump out some helpful debugging information
...@@ -431,17 +426,6 @@ void OopMapSet::all_do(const frame *fr, const RegisterMap *reg_map, ...@@ -431,17 +426,6 @@ void OopMapSet::all_do(const frame *fr, const RegisterMap *reg_map,
} }
} }
} }
#ifdef COMPILER2
if (DoEscapeAnalysis) {
for (OopMapStream oms(map, OopMapValue::stack_obj); !oms.is_done(); oms.next()) {
omv = oms.current();
assert(omv.is_stack_loc(), "should refer to stack location");
oop loc = (oop) fr->oopmapreg_to_location(omv.reg(),reg_map);
oop_fn->do_oop(&loc);
}
}
#endif // COMPILER2
} }
...@@ -540,9 +524,6 @@ void print_register_type(OopMapValue::oop_types x, VMReg optional, ...@@ -540,9 +524,6 @@ void print_register_type(OopMapValue::oop_types x, VMReg optional,
st->print("Derived_oop_" ); st->print("Derived_oop_" );
optional->print_on(st); optional->print_on(st);
break; break;
case OopMapValue::stack_obj:
st->print("Stack");
break;
default: default:
ShouldNotReachHere(); ShouldNotReachHere();
} }
......
...@@ -46,7 +46,7 @@ private: ...@@ -46,7 +46,7 @@ private:
public: public:
// Constants // Constants
enum { type_bits = 6, enum { type_bits = 5,
register_bits = BitsPerShort - type_bits }; register_bits = BitsPerShort - type_bits };
enum { type_shift = 0, enum { type_shift = 0,
...@@ -63,8 +63,7 @@ public: ...@@ -63,8 +63,7 @@ public:
value_value = 2, value_value = 2,
narrowoop_value = 4, narrowoop_value = 4,
callee_saved_value = 8, callee_saved_value = 8,
derived_oop_value= 16, derived_oop_value= 16 };
stack_obj = 32 };
// Constructors // Constructors
OopMapValue () { set_value(0); set_content_reg(VMRegImpl::Bad()); } OopMapValue () { set_value(0); set_content_reg(VMRegImpl::Bad()); }
...@@ -93,14 +92,12 @@ public: ...@@ -93,14 +92,12 @@ public:
bool is_narrowoop() { return mask_bits(value(), type_mask_in_place) == narrowoop_value; } bool is_narrowoop() { return mask_bits(value(), type_mask_in_place) == narrowoop_value; }
bool is_callee_saved() { return mask_bits(value(), type_mask_in_place) == callee_saved_value; } bool is_callee_saved() { return mask_bits(value(), type_mask_in_place) == callee_saved_value; }
bool is_derived_oop() { return mask_bits(value(), type_mask_in_place) == derived_oop_value; } bool is_derived_oop() { return mask_bits(value(), type_mask_in_place) == derived_oop_value; }
bool is_stack_obj() { return mask_bits(value(), type_mask_in_place) == stack_obj; }
void set_oop() { set_value((value() & register_mask_in_place) | oop_value); } void set_oop() { set_value((value() & register_mask_in_place) | oop_value); }
void set_value() { set_value((value() & register_mask_in_place) | value_value); } void set_value() { set_value((value() & register_mask_in_place) | value_value); }
void set_narrowoop() { set_value((value() & register_mask_in_place) | narrowoop_value); } void set_narrowoop() { set_value((value() & register_mask_in_place) | narrowoop_value); }
void set_callee_saved() { set_value((value() & register_mask_in_place) | callee_saved_value); } void set_callee_saved() { set_value((value() & register_mask_in_place) | callee_saved_value); }
void set_derived_oop() { set_value((value() & register_mask_in_place) | derived_oop_value); } void set_derived_oop() { set_value((value() & register_mask_in_place) | derived_oop_value); }
void set_stack_obj() { set_value((value() & register_mask_in_place) | stack_obj); }
VMReg reg() const { return VMRegImpl::as_VMReg(mask_bits(value(), register_mask_in_place) >> register_shift); } VMReg reg() const { return VMRegImpl::as_VMReg(mask_bits(value(), register_mask_in_place) >> register_shift); }
oop_types type() const { return (oop_types)mask_bits(value(), type_mask_in_place); } oop_types type() const { return (oop_types)mask_bits(value(), type_mask_in_place); }
...@@ -180,7 +177,6 @@ class OopMap: public ResourceObj { ...@@ -180,7 +177,6 @@ class OopMap: public ResourceObj {
void set_dead ( VMReg local); void set_dead ( VMReg local);
void set_callee_saved( VMReg local, VMReg caller_machine_register ); void set_callee_saved( VMReg local, VMReg caller_machine_register );
void set_derived_oop ( VMReg local, VMReg derived_from_local_register ); void set_derived_oop ( VMReg local, VMReg derived_from_local_register );
void set_stack_obj( VMReg local);
void set_xxx(VMReg reg, OopMapValue::oop_types x, VMReg optional); void set_xxx(VMReg reg, OopMapValue::oop_types x, VMReg optional);
int heap_size() const; int heap_size() const;
......
...@@ -83,7 +83,7 @@ static bool is_init_with_ea(ciMethod* callee_method, ...@@ -83,7 +83,7 @@ static bool is_init_with_ea(ciMethod* callee_method,
ciMethod* caller_method, Compile* C) { ciMethod* caller_method, Compile* C) {
// True when EA is ON and a java constructor is called or // True when EA is ON and a java constructor is called or
// a super constructor is called from an inlined java constructor. // a super constructor is called from an inlined java constructor.
return DoEscapeAnalysis && EliminateAllocations && return C->do_escape_analysis() && EliminateAllocations &&
( callee_method->is_initializer() || ( callee_method->is_initializer() ||
(caller_method->is_initializer() && (caller_method->is_initializer() &&
caller_method != C->method() && caller_method != C->method() &&
......
...@@ -373,7 +373,7 @@ ...@@ -373,7 +373,7 @@
product(intx, AutoBoxCacheMax, 128, \ product(intx, AutoBoxCacheMax, 128, \
"Sets max value cached by the java.lang.Integer autobox cache") \ "Sets max value cached by the java.lang.Integer autobox cache") \
\ \
product(bool, DoEscapeAnalysis, false, \ product(bool, DoEscapeAnalysis, true, \
"Perform escape analysis") \ "Perform escape analysis") \
\ \
notproduct(bool, PrintEscapeAnalysis, false, \ notproduct(bool, PrintEscapeAnalysis, false, \
......
...@@ -583,18 +583,22 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr ...@@ -583,18 +583,22 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
NOT_PRODUCT( verify_graph_edges(); ) NOT_PRODUCT( verify_graph_edges(); )
// Perform escape analysis // Perform escape analysis
if (_do_escape_analysis) if (_do_escape_analysis && ConnectionGraph::has_candidates(this)) {
_congraph = new ConnectionGraph(this); TracePhase t2("escapeAnalysis", &_t_escapeAnalysis, true);
if (_congraph != NULL) {
NOT_PRODUCT( TracePhase t2("escapeAnalysis", &_t_escapeAnalysis, TimeCompiler); ) _congraph = new(comp_arena()) ConnectionGraph(this);
_congraph->compute_escape(); bool has_non_escaping_obj = _congraph->compute_escape();
if (failing()) return;
#ifndef PRODUCT #ifndef PRODUCT
if (PrintEscapeAnalysis) { if (PrintEscapeAnalysis) {
_congraph->dump(); _congraph->dump();
} }
#endif #endif
if (!has_non_escaping_obj) {
_congraph = NULL;
}
if (failing()) return;
} }
// Now optimize // Now optimize
Optimize(); Optimize();
......
此差异已折叠。
...@@ -178,14 +178,24 @@ public: ...@@ -178,14 +178,24 @@ public:
// count of outgoing edges // count of outgoing edges
uint edge_count() const { return (_edges == NULL) ? 0 : _edges->length(); } uint edge_count() const { return (_edges == NULL) ? 0 : _edges->length(); }
// node index of target of outgoing edge "e" // node index of target of outgoing edge "e"
uint edge_target(uint e) const; uint edge_target(uint e) const {
assert(_edges != NULL, "valid edge index");
return (_edges->at(e) >> EdgeShift);
}
// type of outgoing edge "e" // type of outgoing edge "e"
EdgeType edge_type(uint e) const; EdgeType edge_type(uint e) const {
assert(_edges != NULL, "valid edge index");
return (EdgeType) (_edges->at(e) & EdgeMask);
}
// add a edge of the specified type pointing to the specified target // add a edge of the specified type pointing to the specified target
void add_edge(uint targIdx, EdgeType et); void add_edge(uint targIdx, EdgeType et);
// remove an edge of the specified type pointing to the specified target // remove an edge of the specified type pointing to the specified target
void remove_edge(uint targIdx, EdgeType et); void remove_edge(uint targIdx, EdgeType et);
#ifndef PRODUCT #ifndef PRODUCT
void dump() const; void dump() const;
#endif #endif
...@@ -194,7 +204,7 @@ public: ...@@ -194,7 +204,7 @@ public:
class ConnectionGraph: public ResourceObj { class ConnectionGraph: public ResourceObj {
private: private:
GrowableArray<PointsToNode>* _nodes; // Connection graph nodes indexed GrowableArray<PointsToNode> _nodes; // Connection graph nodes indexed
// by ideal node index. // by ideal node index.
Unique_Node_List _delayed_worklist; // Nodes to be processed before Unique_Node_List _delayed_worklist; // Nodes to be processed before
...@@ -207,9 +217,6 @@ private: ...@@ -207,9 +217,6 @@ private:
// is still being collected. If false, // is still being collected. If false,
// no new nodes will be processed. // no new nodes will be processed.
bool _has_allocations; // Indicates whether method has any
// non-escaping allocations.
uint _phantom_object; // Index of globally escaping object uint _phantom_object; // Index of globally escaping object
// that pointer values loaded from // that pointer values loaded from
// a field which has not been set // a field which has not been set
...@@ -217,14 +224,13 @@ private: ...@@ -217,14 +224,13 @@ private:
Compile * _compile; // Compile object for current compilation Compile * _compile; // Compile object for current compilation
// address of an element in _nodes. Used when the element is to be modified // Address of an element in _nodes. Used when the element is to be modified
PointsToNode *ptnode_adr(uint idx) { PointsToNode *ptnode_adr(uint idx) const {
if ((uint)_nodes->length() <= idx) { // There should be no new ideal nodes during ConnectionGraph build,
// expand _nodes array // growableArray::adr_at() will throw assert otherwise.
PointsToNode dummy = _nodes->at_grow(idx); return _nodes.adr_at(idx);
}
return _nodes->adr_at(idx);
} }
uint nodes_size() const { return _nodes.length(); }
// Add node to ConnectionGraph. // Add node to ConnectionGraph.
void add_node(Node *n, PointsToNode::NodeType nt, PointsToNode::EscapeState es, bool done); void add_node(Node *n, PointsToNode::NodeType nt, PointsToNode::EscapeState es, bool done);
...@@ -307,30 +313,30 @@ private: ...@@ -307,30 +313,30 @@ private:
// Set the escape state of a node // Set the escape state of a node
void set_escape_state(uint ni, PointsToNode::EscapeState es); void set_escape_state(uint ni, PointsToNode::EscapeState es);
// Get Compile object for current compilation.
Compile *C() const { return _compile; }
public: public:
ConnectionGraph(Compile *C); ConnectionGraph(Compile *C);
// Check for non-escaping candidates
static bool has_candidates(Compile *C);
// Compute the escape information // Compute the escape information
void compute_escape(); bool compute_escape();
// escape state of a node // escape state of a node
PointsToNode::EscapeState escape_state(Node *n, PhaseTransform *phase); PointsToNode::EscapeState escape_state(Node *n, PhaseTransform *phase);
// other information we have collected // other information we have collected
bool is_scalar_replaceable(Node *n) { bool is_scalar_replaceable(Node *n) {
if (_collecting) if (_collecting || (n->_idx >= nodes_size()))
return false; return false;
PointsToNode ptn = _nodes->at_grow(n->_idx); PointsToNode* ptn = ptnode_adr(n->_idx);
return ptn.escape_state() == PointsToNode::NoEscape && ptn._scalar_replaceable; return ptn->escape_state() == PointsToNode::NoEscape && ptn->_scalar_replaceable;
} }
bool hidden_alias(Node *n) { bool hidden_alias(Node *n) {
if (_collecting) if (_collecting || (n->_idx >= nodes_size()))
return true; return true;
PointsToNode ptn = _nodes->at_grow(n->_idx); PointsToNode* ptn = ptnode_adr(n->_idx);
return (ptn.escape_state() != PointsToNode::NoEscape) || ptn._hidden_alias; return (ptn->escape_state() != PointsToNode::NoEscape) || ptn->_hidden_alias;
} }
#ifndef PRODUCT #ifndef PRODUCT
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册