提交 eb7c3289 编写于 作者: K kvn

6674588: (Escape Analysis) Improve Escape Analysis code

Summary: Current EA code has several problems which have to be fixed.
Reviewed-by: jrose, sgoldman
上级 53f4ef4a
...@@ -164,6 +164,7 @@ callGenerator.hpp deoptimization.hpp ...@@ -164,6 +164,7 @@ callGenerator.hpp deoptimization.hpp
callGenerator.hpp type.hpp callGenerator.hpp type.hpp
callnode.cpp callnode.hpp callnode.cpp callnode.hpp
callnode.cpp bcEscapeAnalyzer.hpp
callnode.cpp escape.hpp callnode.cpp escape.hpp
callnode.cpp locknode.hpp callnode.cpp locknode.hpp
callnode.cpp machnode.hpp callnode.cpp machnode.hpp
...@@ -176,7 +177,6 @@ callnode.cpp rootnode.hpp ...@@ -176,7 +177,6 @@ callnode.cpp rootnode.hpp
callnode.cpp runtime.hpp callnode.cpp runtime.hpp
callnode.hpp connode.hpp callnode.hpp connode.hpp
callnode.hpp escape.hpp
callnode.hpp mulnode.hpp callnode.hpp mulnode.hpp
callnode.hpp multnode.hpp callnode.hpp multnode.hpp
callnode.hpp opcodes.hpp callnode.hpp opcodes.hpp
...@@ -347,7 +347,6 @@ connode.cpp addnode.hpp ...@@ -347,7 +347,6 @@ connode.cpp addnode.hpp
connode.cpp allocation.inline.hpp connode.cpp allocation.inline.hpp
connode.cpp compile.hpp connode.cpp compile.hpp
connode.cpp connode.hpp connode.cpp connode.hpp
connode.cpp escape.hpp
connode.cpp machnode.hpp connode.cpp machnode.hpp
connode.cpp matcher.hpp connode.cpp matcher.hpp
connode.cpp memnode.hpp connode.cpp memnode.hpp
...@@ -844,7 +843,6 @@ phaseX.cpp block.hpp ...@@ -844,7 +843,6 @@ phaseX.cpp block.hpp
phaseX.cpp callnode.hpp phaseX.cpp callnode.hpp
phaseX.cpp cfgnode.hpp phaseX.cpp cfgnode.hpp
phaseX.cpp connode.hpp phaseX.cpp connode.hpp
phaseX.cpp escape.hpp
phaseX.cpp loopnode.hpp phaseX.cpp loopnode.hpp
phaseX.cpp machnode.hpp phaseX.cpp machnode.hpp
phaseX.cpp opcodes.hpp phaseX.cpp opcodes.hpp
......
...@@ -382,6 +382,12 @@ ...@@ -382,6 +382,12 @@
product(bool, EliminateAllocations, true, \ product(bool, EliminateAllocations, true, \
"Use escape analysis to eliminate allocations") \ "Use escape analysis to eliminate allocations") \
\ \
notproduct(bool, PrintEliminateAllocations, false, \
"Print out when allocations are eliminated") \
\
product(intx, EliminateAllocationArraySizeLimit, 64, \
"Array size (number of elements) limit for scalar replacement") \
\
product(intx, MaxLabelRootDepth, 1100, \ product(intx, MaxLabelRootDepth, 1100, \
"Maximum times call Label_Root to prevent stack overflow") \ "Maximum times call Label_Root to prevent stack overflow") \
......
...@@ -624,6 +624,87 @@ uint CallNode::match_edge(uint idx) const { ...@@ -624,6 +624,87 @@ uint CallNode::match_edge(uint idx) const {
return 0; return 0;
} }
//
// Determine whether the call could modify a memory value of the
// specified address type
//
bool CallNode::may_modify(const TypePtr *addr_t, PhaseTransform *phase) {
const TypeOopPtr *adrInst_t = addr_t->isa_oopptr();
// if not an InstPtr or not an instance type, assume the worst
if (adrInst_t == NULL || !adrInst_t->is_instance_field()) {
return true;
}
Compile *C = phase->C;
int offset = adrInst_t->offset();
assert(offset >= 0, "should be valid offset");
assert(addr_t->isa_instptr() || addr_t->isa_aryptr(), "only instances or arrays are expected");
int base_idx = C->get_alias_index(adrInst_t);
ciMethod * meth = is_CallStaticJava() ? as_CallStaticJava()->method() : NULL;
BCEscapeAnalyzer *bcea = (meth != NULL) ? meth->get_bcea() : NULL;
const TypeTuple * d = tf()->domain();
for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
const Type* t = d->field_at(i);
Node *arg = in(i);
const Type *at = phase->type(arg);
if (at == TypePtr::NULL_PTR || at == Type::TOP)
continue; // null can't affect anything
const TypeOopPtr *at_ptr = at->isa_oopptr();
if (!arg->is_top() && (t->isa_oopptr() != NULL ||
t->isa_ptr() && at_ptr != NULL)) {
assert(at_ptr != NULL, "expecting an OopPtr");
// If we have found an argument matching adr_base_t, check if the field
// at the specified offset is modified. Since we don't know the size,
// assume 8.
int at_idx = C->get_alias_index(at_ptr->add_offset(offset)->isa_oopptr());
if (base_idx == at_idx &&
(bcea == NULL ||
bcea->is_arg_modified(i - TypeFunc::Parms, offset, 8))) {
return true;
}
}
}
return false;
}
// Does this call have a direct reference to n other than debug information?
bool CallNode::has_non_debug_use(Node *n) {
const TypeTuple * d = tf()->domain();
for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
Node *arg = in(i);
if (arg == n) {
return true;
}
}
return false;
}
// Returns the unique CheckCastPP of a call
// or 'this' if there are several CheckCastPP
// or returns NULL if there is no one.
Node *CallNode::result_cast() {
Node *cast = NULL;
Node *p = proj_out(TypeFunc::Parms);
if (p == NULL)
return NULL;
for (DUIterator_Fast imax, i = p->fast_outs(imax); i < imax; i++) {
Node *use = p->fast_out(i);
if (use->is_CheckCastPP()) {
if (cast != NULL) {
return this; // more than 1 CheckCastPP
}
cast = use;
}
}
return cast;
}
//============================================================================= //=============================================================================
uint CallJavaNode::size_of() const { return sizeof(*this); } uint CallJavaNode::size_of() const { return sizeof(*this); }
uint CallJavaNode::cmp( const Node &n ) const { uint CallJavaNode::cmp( const Node &n ) const {
......
...@@ -388,6 +388,9 @@ public: ...@@ -388,6 +388,9 @@ public:
void set_next_exception(SafePointNode* n); void set_next_exception(SafePointNode* n);
bool has_exceptions() const { return next_exception() != NULL; } bool has_exceptions() const { return next_exception() != NULL; }
// Does this node have a use of n other than in debug information?
virtual bool has_non_debug_use(Node *n) {return false; }
// Standard Node stuff // Standard Node stuff
virtual int Opcode() const; virtual int Opcode() const;
virtual bool pinned() const { return true; } virtual bool pinned() const { return true; }
...@@ -457,7 +460,6 @@ public: ...@@ -457,7 +460,6 @@ public:
const TypeFunc *_tf; // Function type const TypeFunc *_tf; // Function type
address _entry_point; // Address of method being called address _entry_point; // Address of method being called
float _cnt; // Estimate of number of times called float _cnt; // Estimate of number of times called
PointsToNode::EscapeState _escape_state;
CallNode(const TypeFunc* tf, address addr, const TypePtr* adr_type) CallNode(const TypeFunc* tf, address addr, const TypePtr* adr_type)
: SafePointNode(tf->domain()->cnt(), NULL, adr_type), : SafePointNode(tf->domain()->cnt(), NULL, adr_type),
...@@ -467,7 +469,6 @@ public: ...@@ -467,7 +469,6 @@ public:
{ {
init_class_id(Class_Call); init_class_id(Class_Call);
init_flags(Flag_is_Call); init_flags(Flag_is_Call);
_escape_state = PointsToNode::UnknownEscape;
} }
const TypeFunc* tf() const { return _tf; } const TypeFunc* tf() const { return _tf; }
...@@ -493,6 +494,15 @@ public: ...@@ -493,6 +494,15 @@ public:
// the node the JVMState must be cloned. // the node the JVMState must be cloned.
virtual void clone_jvms() { } // default is not to clone virtual void clone_jvms() { } // default is not to clone
// Returns true if the call may modify n
virtual bool may_modify(const TypePtr *addr_t, PhaseTransform *phase);
// Does this node have a use of n other than in debug information?
virtual bool has_non_debug_use(Node *n);
// Returns the unique CheckCastPP of a call
// or result projection is there are several CheckCastPP
// or returns NULL if there is no one.
Node *result_cast();
virtual uint match_edge(uint idx) const; virtual uint match_edge(uint idx) const;
#ifndef PRODUCT #ifndef PRODUCT
...@@ -689,6 +699,9 @@ public: ...@@ -689,6 +699,9 @@ public:
virtual uint ideal_reg() const { return Op_RegP; } virtual uint ideal_reg() const { return Op_RegP; }
virtual bool guaranteed_safepoint() { return false; } virtual bool guaranteed_safepoint() { return false; }
// allocations do not modify their arguments
virtual bool may_modify(const TypePtr *addr_t, PhaseTransform *phase) { return false;}
// Pattern-match a possible usage of AllocateNode. // Pattern-match a possible usage of AllocateNode.
// Return null if no allocation is recognized. // Return null if no allocation is recognized.
// The operand is the pointer produced by the (possible) allocation. // The operand is the pointer produced by the (possible) allocation.
...@@ -801,6 +814,9 @@ public: ...@@ -801,6 +814,9 @@ public:
// mark node as eliminated and update the counter if there is one // mark node as eliminated and update the counter if there is one
void set_eliminated(); void set_eliminated();
// locking does not modify its arguments
virtual bool may_modify(const TypePtr *addr_t, PhaseTransform *phase){ return false;}
#ifndef PRODUCT #ifndef PRODUCT
void create_lock_counter(JVMState* s); void create_lock_counter(JVMState* s);
NamedCounter* counter() const { return _counter; } NamedCounter* counter() const { return _counter; }
......
...@@ -407,11 +407,6 @@ uint Compile::scratch_emit_size(const Node* n) { ...@@ -407,11 +407,6 @@ uint Compile::scratch_emit_size(const Node* n) {
return buf.code_size(); return buf.code_size();
} }
void Compile::record_for_escape_analysis(Node* n) {
if (_congraph != NULL)
_congraph->record_for_escape_analysis(n);
}
// ============================================================================ // ============================================================================
//------------------------------Compile standard------------------------------- //------------------------------Compile standard-------------------------------
...@@ -494,9 +489,6 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr ...@@ -494,9 +489,6 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
PhaseGVN gvn(node_arena(), estimated_size); PhaseGVN gvn(node_arena(), estimated_size);
set_initial_gvn(&gvn); set_initial_gvn(&gvn);
if (_do_escape_analysis)
_congraph = new ConnectionGraph(this);
{ // Scope for timing the parser { // Scope for timing the parser
TracePhase t3("parse", &_t_parser, true); TracePhase t3("parse", &_t_parser, true);
...@@ -581,6 +573,8 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr ...@@ -581,6 +573,8 @@ 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)
_congraph = new ConnectionGraph(this);
if (_congraph != NULL) { if (_congraph != NULL) {
NOT_PRODUCT( TracePhase t2("escapeAnalysis", &_t_escapeAnalysis, TimeCompiler); ) NOT_PRODUCT( TracePhase t2("escapeAnalysis", &_t_escapeAnalysis, TimeCompiler); )
_congraph->compute_escape(); _congraph->compute_escape();
......
...@@ -485,7 +485,6 @@ class Compile : public Phase { ...@@ -485,7 +485,6 @@ class Compile : public Phase {
PhaseGVN* initial_gvn() { return _initial_gvn; } PhaseGVN* initial_gvn() { return _initial_gvn; }
Unique_Node_List* for_igvn() { return _for_igvn; } Unique_Node_List* for_igvn() { return _for_igvn; }
inline void record_for_igvn(Node* n); // Body is after class Unique_Node_List. inline void record_for_igvn(Node* n); // Body is after class Unique_Node_List.
void record_for_escape_analysis(Node* n);
void set_initial_gvn(PhaseGVN *gvn) { _initial_gvn = gvn; } void set_initial_gvn(PhaseGVN *gvn) { _initial_gvn = gvn; }
void set_for_igvn(Unique_Node_List *for_igvn) { _for_igvn = for_igvn; } void set_for_igvn(Unique_Node_List *for_igvn) { _for_igvn = for_igvn; }
......
此差异已折叠。
...@@ -25,14 +25,15 @@ ...@@ -25,14 +25,15 @@
// //
// Adaptation for C2 of the escape analysis algorithm described in: // Adaptation for C2 of the escape analysis algorithm described in:
// //
// [Choi99] Jong-Deok Shoi, Manish Gupta, Mauricio Seffano, Vugranam C. Sreedhar, // [Choi99] Jong-Deok Shoi, Manish Gupta, Mauricio Seffano,
// Sam Midkiff, "Escape Analysis for Java", Procedings of ACM SIGPLAN // Vugranam C. Sreedhar, Sam Midkiff,
// OOPSLA Conference, November 1, 1999 // "Escape Analysis for Java", Procedings of ACM SIGPLAN
// OOPSLA Conference, November 1, 1999
// //
// The flow-insensitive analysis described in the paper has been implemented. // The flow-insensitive analysis described in the paper has been implemented.
// //
// The analysis requires construction of a "connection graph" (CG) for the method being // The analysis requires construction of a "connection graph" (CG) for
// analyzed. The nodes of the connection graph are: // the method being analyzed. The nodes of the connection graph are:
// //
// - Java objects (JO) // - Java objects (JO)
// - Local variables (LV) // - Local variables (LV)
...@@ -40,47 +41,51 @@ ...@@ -40,47 +41,51 @@
// //
// The CG contains 3 types of edges: // The CG contains 3 types of edges:
// //
// - PointsTo (-P>) {LV,OF} to JO // - PointsTo (-P>) {LV, OF} to JO
// - Deferred (-D>) from {LV, OF} to {LV, OF} // - Deferred (-D>) from {LV, OF} to {LV, OF}
// - Field (-F>) from JO to OF // - Field (-F>) from JO to OF
// //
// The following utility functions is used by the algorithm: // The following utility functions is used by the algorithm:
// //
// PointsTo(n) - n is any CG node, it returns the set of JO that n could // PointsTo(n) - n is any CG node, it returns the set of JO that n could
// point to. // point to.
// //
// The algorithm describes how to construct the connection graph in the following 4 cases: // The algorithm describes how to construct the connection graph
// in the following 4 cases:
// //
// Case Edges Created // Case Edges Created
// //
// (1) p = new T() LV -P> JO // (1) p = new T() LV -P> JO
// (2) p = q LV -D> LV // (2) p = q LV -D> LV
// (3) p.f = q JO -F> OF, OF -D> LV // (3) p.f = q JO -F> OF, OF -D> LV
// (4) p = q.f JO -F> OF, LV -D> OF // (4) p = q.f JO -F> OF, LV -D> OF
// //
// In all these cases, p and q are local variables. For static field references, we can // In all these cases, p and q are local variables. For static field
// construct a local variable containing a reference to the static memory. // references, we can construct a local variable containing a reference
// to the static memory.
// //
// C2 does not have local variables. However for the purposes of constructing // C2 does not have local variables. However for the purposes of constructing
// the connection graph, the following IR nodes are treated as local variables: // the connection graph, the following IR nodes are treated as local variables:
// Phi (pointer values) // Phi (pointer values)
// LoadP // LoadP
// Proj (value returned from callnodes including allocations) // Proj#5 (value returned from callnodes including allocations)
// CheckCastPP // CheckCastPP, CastPP
// //
// The LoadP, Proj and CheckCastPP behave like variables assigned to only once. Only // The LoadP, Proj and CheckCastPP behave like variables assigned to only once.
// a Phi can have multiple assignments. Each input to a Phi is treated // Only a Phi can have multiple assignments. Each input to a Phi is treated
// as an assignment to it. // as an assignment to it.
// //
// The following note types are JavaObject: // The following node types are JavaObject:
// //
// top() // top()
// Allocate // Allocate
// AllocateArray // AllocateArray
// Parm (for incoming arguments) // Parm (for incoming arguments)
// CastX2P ("unsafe" operations)
// CreateEx // CreateEx
// ConP // ConP
// LoadKlass // LoadKlass
// ThreadLocal
// //
// AddP nodes are fields. // AddP nodes are fields.
// //
...@@ -89,7 +94,7 @@ ...@@ -89,7 +94,7 @@
// source. This results in a graph with no deferred edges, only: // source. This results in a graph with no deferred edges, only:
// //
// LV -P> JO // LV -P> JO
// OF -P> JO // OF -P> JO (the object whose oop is stored in the field)
// JO -F> OF // JO -F> OF
// //
// Then, for each node which is GlobalEscape, anything it could point to // Then, for each node which is GlobalEscape, anything it could point to
...@@ -110,17 +115,18 @@ class PointsToNode { ...@@ -110,17 +115,18 @@ class PointsToNode {
friend class ConnectionGraph; friend class ConnectionGraph;
public: public:
typedef enum { typedef enum {
UnknownType = 0, UnknownType = 0,
JavaObject = 1, JavaObject = 1,
LocalVar = 2, LocalVar = 2,
Field = 3 Field = 3
} NodeType; } NodeType;
typedef enum { typedef enum {
UnknownEscape = 0, UnknownEscape = 0,
NoEscape = 1, NoEscape = 1, // A scalar replaceable object with unique type.
ArgEscape = 2, ArgEscape = 2, // An object passed as argument or referenced by
GlobalEscape = 3 // argument (and not globally escape during call).
GlobalEscape = 3 // An object escapes the method and thread.
} EscapeState; } EscapeState;
typedef enum { typedef enum {
...@@ -140,19 +146,25 @@ private: ...@@ -140,19 +146,25 @@ private:
NodeType _type; NodeType _type;
EscapeState _escape; EscapeState _escape;
GrowableArray<uint>* _edges; // outgoing edges GrowableArray<uint>* _edges; // outgoing edges
int _offset; // for fields
bool _unique_type; // For allocated objects, this node may be a unique type
public: public:
Node* _node; // Ideal node corresponding to this PointsTo node Node* _node; // Ideal node corresponding to this PointsTo node.
int _inputs_processed; // the number of Phi inputs that have been processed so far int _offset; // Object fields offsets.
bool _hidden_alias; // this node is an argument to a function which may return it bool _scalar_replaceable;// Not escaped object could be replaced with scalar
// creating a hidden alias bool _hidden_alias; // This node is an argument to a function.
// which may return it creating a hidden alias.
PointsToNode():
_type(UnknownType),
_escape(UnknownEscape),
_edges(NULL),
_node(NULL),
_offset(-1),
_scalar_replaceable(true),
_hidden_alias(false) {}
PointsToNode(): _offset(-1), _type(UnknownType), _escape(UnknownEscape), _edges(NULL), _node(NULL), _inputs_processed(0), _hidden_alias(false), _unique_type(true) {}
EscapeState escape_state() const { return _escape; } EscapeState escape_state() const { return _escape; }
NodeType node_type() const { return _type;} NodeType node_type() const { return _type;}
int offset() { return _offset;} int offset() { return _offset;}
...@@ -182,22 +194,28 @@ public: ...@@ -182,22 +194,28 @@ public:
class ConnectionGraph: public ResourceObj { class ConnectionGraph: public ResourceObj {
private: private:
enum { GrowableArray<PointsToNode>* _nodes; // Connection graph nodes indexed
INITIAL_NODE_COUNT = 100 // initial size of _nodes array // by ideal node index.
};
Unique_Node_List _delayed_worklist; // Nodes to be processed before
// the call build_connection_graph().
VectorSet _processed; // Records which nodes have been
// processed.
GrowableArray<PointsToNode>* _nodes; // connection graph nodes Indexed by ideal bool _collecting; // Indicates whether escape information
// node index // is still being collected. If false,
Unique_Node_List _deferred; // Phi's to be processed after parsing // no new nodes will be processed.
VectorSet _processed; // records which nodes have been processed
bool _collecting; // indicates whether escape information is bool _has_allocations; // Indicates whether method has any
// still being collected. If false, no new // non-escaping allocations.
// nodes will be processed
uint _phantom_object; // index of globally escaping object that uint _phantom_object; // Index of globally escaping object
// pointer values loaded from a field which // that pointer values loaded from
// has not been set are assumed to point to // a field which has not been set
Compile * _compile; // Compile object for current compilation // are assumed to point to.
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) {
...@@ -208,8 +226,11 @@ private: ...@@ -208,8 +226,11 @@ private:
return _nodes->adr_at(idx); return _nodes->adr_at(idx);
} }
// Add node to ConnectionGraph.
void add_node(Node *n, PointsToNode::NodeType nt, PointsToNode::EscapeState es, bool done);
// offset of a field reference // offset of a field reference
int type_to_offset(const Type *t); int address_offset(Node* adr, PhaseTransform *phase);
// compute the escape state for arguments to a call // compute the escape state for arguments to a call
void process_call_arguments(CallNode *call, PhaseTransform *phase); void process_call_arguments(CallNode *call, PhaseTransform *phase);
...@@ -217,12 +238,11 @@ private: ...@@ -217,12 +238,11 @@ private:
// compute the escape state for the return value of a call // compute the escape state for the return value of a call
void process_call_result(ProjNode *resproj, PhaseTransform *phase); void process_call_result(ProjNode *resproj, PhaseTransform *phase);
// compute the escape state of a Phi. This may be called multiple // Populate Connection Graph with Ideal nodes.
// times as new inputs are added to the Phi. void record_for_escape_analysis(Node *n, PhaseTransform *phase);
void process_phi_escape(PhiNode *phi, PhaseTransform *phase);
// compute the escape state of an ideal node. // Build Connection Graph and set nodes escape state.
void record_escape_work(Node *n, PhaseTransform *phase); void build_connection_graph(Node *n, PhaseTransform *phase);
// walk the connection graph starting at the node corresponding to "n" and // walk the connection graph starting at the node corresponding to "n" and
// add the index of everything it could point to, to "ptset". This may cause // add the index of everything it could point to, to "ptset". This may cause
...@@ -241,8 +261,8 @@ private: ...@@ -241,8 +261,8 @@ private:
// a pointsto edge is added if it is a JavaObject // a pointsto edge is added if it is a JavaObject
void add_edge_from_fields(uint adr, uint to_i, int offs); void add_edge_from_fields(uint adr, uint to_i, int offs);
// Add a deferred edge from node given by "from_i" to any field of adr_i whose offset // Add a deferred edge from node given by "from_i" to any field
// matches "offset" // of adr_i whose offset matches "offset"
void add_deferred_edge_to_fields(uint from_i, uint adr, int offs); void add_deferred_edge_to_fields(uint from_i, uint adr, int offs);
...@@ -262,6 +282,8 @@ private: ...@@ -262,6 +282,8 @@ private:
PhiNode *create_split_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *> &orig_phi_worklist, PhaseGVN *igvn, bool &new_created); PhiNode *create_split_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *> &orig_phi_worklist, PhaseGVN *igvn, bool &new_created);
PhiNode *split_memory_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *> &orig_phi_worklist, PhaseGVN *igvn); PhiNode *split_memory_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *> &orig_phi_worklist, PhaseGVN *igvn);
Node *find_mem(Node *mem, int alias_idx, PhaseGVN *igvn); Node *find_mem(Node *mem, int alias_idx, PhaseGVN *igvn);
Node *find_inst_mem(Node *mem, int alias_idx,GrowableArray<PhiNode *> &orig_phi_worklist, PhaseGVN *igvn);
// Propagate unique types created for unescaped allocated objects // Propagate unique types created for unescaped allocated objects
// through the graph // through the graph
void split_unique_types(GrowableArray<Node *> &alloc_worklist); void split_unique_types(GrowableArray<Node *> &alloc_worklist);
...@@ -285,26 +307,24 @@ private: ...@@ -285,26 +307,24 @@ 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);
// bypass any casts and return the node they refer to
Node * skip_casts(Node *n);
// Get Compile object for current compilation. // Get Compile object for current compilation.
Compile *C() const { return _compile; } Compile *C() const { return _compile; }
public: public:
ConnectionGraph(Compile *C); ConnectionGraph(Compile *C);
// record a Phi for later processing. // Compute the escape information
void record_for_escape_analysis(Node *n);
// process a node and fill in its connection graph node
void record_escape(Node *n, PhaseTransform *phase);
// All nodes have been recorded, compute the escape information
void compute_escape(); void 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
bool is_scalar_replaceable(Node *n) {
if (_collecting)
return false;
PointsToNode ptn = _nodes->at_grow(n->_idx);
return ptn.escape_state() == PointsToNode::NoEscape && ptn._scalar_replaceable;
}
bool hidden_alias(Node *n) { bool hidden_alias(Node *n) {
if (_collecting) if (_collecting)
......
...@@ -812,8 +812,7 @@ int Node::disconnect_inputs(Node *n) { ...@@ -812,8 +812,7 @@ int Node::disconnect_inputs(Node *n) {
Node* Node::uncast() const { Node* Node::uncast() const {
// Should be inline: // Should be inline:
//return is_ConstraintCast() ? uncast_helper(this) : (Node*) this; //return is_ConstraintCast() ? uncast_helper(this) : (Node*) this;
if (is_ConstraintCast() || if (is_ConstraintCast() || is_CheckCastPP())
(is_Type() && req() == 2 && Opcode() == Op_CheckCastPP))
return uncast_helper(this); return uncast_helper(this);
else else
return (Node*) this; return (Node*) this;
...@@ -827,7 +826,7 @@ Node* Node::uncast_helper(const Node* p) { ...@@ -827,7 +826,7 @@ Node* Node::uncast_helper(const Node* p) {
break; break;
} else if (p->is_ConstraintCast()) { } else if (p->is_ConstraintCast()) {
p = p->in(1); p = p->in(1);
} else if (p->is_Type() && p->Opcode() == Op_CheckCastPP) { } else if (p->is_CheckCastPP()) {
p = p->in(1); p = p->in(1);
} else { } else {
break; break;
......
...@@ -1328,7 +1328,6 @@ public: ...@@ -1328,7 +1328,6 @@ public:
// Inline definition of Compile::record_for_igvn must be deferred to this point. // Inline definition of Compile::record_for_igvn must be deferred to this point.
inline void Compile::record_for_igvn(Node* n) { inline void Compile::record_for_igvn(Node* n) {
_for_igvn->push(n); _for_igvn->push(n);
record_for_escape_analysis(n);
} }
//------------------------------Node_Stack------------------------------------- //------------------------------Node_Stack-------------------------------------
......
...@@ -587,11 +587,6 @@ ConNode* PhaseValues::uncached_makecon(const Type *t) { ...@@ -587,11 +587,6 @@ ConNode* PhaseValues::uncached_makecon(const Type *t) {
Node_Notes* loc = C->locate_node_notes(nna, x->_idx, true); Node_Notes* loc = C->locate_node_notes(nna, x->_idx, true);
loc->clear(); // do not put debug info on constants loc->clear(); // do not put debug info on constants
} }
// Collect points-to information for escape analysys
ConnectionGraph *cgr = C->congraph();
if (cgr != NULL) {
cgr->record_escape(x, this);
}
} else { } else {
x->destruct(); // Hit, destroy duplicate constant x->destruct(); // Hit, destroy duplicate constant
x = k; // use existing constant x = k; // use existing constant
...@@ -714,12 +709,6 @@ Node *PhaseGVN::transform_no_reclaim( Node *n ) { ...@@ -714,12 +709,6 @@ Node *PhaseGVN::transform_no_reclaim( Node *n ) {
return i; return i;
} }
// Collect points-to information for escape analysys
ConnectionGraph *cgr = C->congraph();
if (cgr != NULL) {
cgr->record_escape(k, this);
}
// Return Idealized original // Return Idealized original
return k; return k;
} }
...@@ -1245,7 +1234,7 @@ void PhaseIterGVN::add_users_to_worklist( Node *n ) { ...@@ -1245,7 +1234,7 @@ void PhaseIterGVN::add_users_to_worklist( Node *n ) {
uint use_op = use->Opcode(); uint use_op = use->Opcode();
// If changed Cast input, check Phi users for simple cycles // If changed Cast input, check Phi users for simple cycles
if( use->is_ConstraintCast() || use->Opcode() == Op_CheckCastPP ) { if( use->is_ConstraintCast() || use->is_CheckCastPP() ) {
for (DUIterator_Fast i2max, i2 = use->fast_outs(i2max); i2 < i2max; i2++) { for (DUIterator_Fast i2max, i2 = use->fast_outs(i2max); i2 < i2max; i2++) {
Node* u = use->fast_out(i2); Node* u = use->fast_out(i2);
if (u->is_Phi()) if (u->is_Phi())
......
...@@ -1276,6 +1276,9 @@ void Arguments::set_aggressive_opts_flags() { ...@@ -1276,6 +1276,9 @@ void Arguments::set_aggressive_opts_flags() {
sprintf(buffer, "java.lang.Integer.IntegerCache.high=%d", AutoBoxCacheMax); sprintf(buffer, "java.lang.Integer.IntegerCache.high=%d", AutoBoxCacheMax);
add_property(buffer); add_property(buffer);
} }
if (AggressiveOpts && FLAG_IS_DEFAULT(DoEscapeAnalysis)) {
FLAG_SET_DEFAULT(DoEscapeAnalysis, true);
}
#endif #endif
if (AggressiveOpts) { if (AggressiveOpts) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册