6674588: (Escape Analysis) Improve Escape Analysis code
Current EA code has several problems which have to be fixed. Reviewed-by: jrose, sgoldman
This commit is contained in:
parent
30dc0edfc8
commit
fc0117cb9a
@ -164,6 +164,7 @@ callGenerator.hpp deoptimization.hpp
|
||||
callGenerator.hpp type.hpp
|
||||
|
||||
callnode.cpp callnode.hpp
|
||||
callnode.cpp bcEscapeAnalyzer.hpp
|
||||
callnode.cpp escape.hpp
|
||||
callnode.cpp locknode.hpp
|
||||
callnode.cpp machnode.hpp
|
||||
@ -176,7 +177,6 @@ callnode.cpp rootnode.hpp
|
||||
callnode.cpp runtime.hpp
|
||||
|
||||
callnode.hpp connode.hpp
|
||||
callnode.hpp escape.hpp
|
||||
callnode.hpp mulnode.hpp
|
||||
callnode.hpp multnode.hpp
|
||||
callnode.hpp opcodes.hpp
|
||||
@ -347,7 +347,6 @@ connode.cpp addnode.hpp
|
||||
connode.cpp allocation.inline.hpp
|
||||
connode.cpp compile.hpp
|
||||
connode.cpp connode.hpp
|
||||
connode.cpp escape.hpp
|
||||
connode.cpp machnode.hpp
|
||||
connode.cpp matcher.hpp
|
||||
connode.cpp memnode.hpp
|
||||
@ -844,7 +843,6 @@ phaseX.cpp block.hpp
|
||||
phaseX.cpp callnode.hpp
|
||||
phaseX.cpp cfgnode.hpp
|
||||
phaseX.cpp connode.hpp
|
||||
phaseX.cpp escape.hpp
|
||||
phaseX.cpp loopnode.hpp
|
||||
phaseX.cpp machnode.hpp
|
||||
phaseX.cpp opcodes.hpp
|
||||
|
@ -382,6 +382,12 @@
|
||||
product(bool, EliminateAllocations, true, \
|
||||
"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, \
|
||||
"Maximum times call Label_Root to prevent stack overflow") \
|
||||
|
||||
|
@ -624,6 +624,87 @@ uint CallNode::match_edge(uint idx) const {
|
||||
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::cmp( const Node &n ) const {
|
||||
|
@ -388,6 +388,9 @@ public:
|
||||
void set_next_exception(SafePointNode* n);
|
||||
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
|
||||
virtual int Opcode() const;
|
||||
virtual bool pinned() const { return true; }
|
||||
@ -457,7 +460,6 @@ public:
|
||||
const TypeFunc *_tf; // Function type
|
||||
address _entry_point; // Address of method being called
|
||||
float _cnt; // Estimate of number of times called
|
||||
PointsToNode::EscapeState _escape_state;
|
||||
|
||||
CallNode(const TypeFunc* tf, address addr, const TypePtr* adr_type)
|
||||
: SafePointNode(tf->domain()->cnt(), NULL, adr_type),
|
||||
@ -467,7 +469,6 @@ public:
|
||||
{
|
||||
init_class_id(Class_Call);
|
||||
init_flags(Flag_is_Call);
|
||||
_escape_state = PointsToNode::UnknownEscape;
|
||||
}
|
||||
|
||||
const TypeFunc* tf() const { return _tf; }
|
||||
@ -493,6 +494,15 @@ public:
|
||||
// the node the JVMState must be cloned.
|
||||
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;
|
||||
|
||||
#ifndef PRODUCT
|
||||
@ -689,6 +699,9 @@ public:
|
||||
virtual uint ideal_reg() const { return Op_RegP; }
|
||||
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.
|
||||
// Return null if no allocation is recognized.
|
||||
// The operand is the pointer produced by the (possible) allocation.
|
||||
@ -801,6 +814,9 @@ public:
|
||||
// mark node as eliminated and update the counter if there is one
|
||||
void set_eliminated();
|
||||
|
||||
// locking does not modify its arguments
|
||||
virtual bool may_modify(const TypePtr *addr_t, PhaseTransform *phase){ return false;}
|
||||
|
||||
#ifndef PRODUCT
|
||||
void create_lock_counter(JVMState* s);
|
||||
NamedCounter* counter() const { return _counter; }
|
||||
|
@ -407,11 +407,6 @@ uint Compile::scratch_emit_size(const Node* n) {
|
||||
return buf.code_size();
|
||||
}
|
||||
|
||||
void Compile::record_for_escape_analysis(Node* n) {
|
||||
if (_congraph != NULL)
|
||||
_congraph->record_for_escape_analysis(n);
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================
|
||||
//------------------------------Compile standard-------------------------------
|
||||
@ -494,9 +489,6 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
|
||||
PhaseGVN gvn(node_arena(), estimated_size);
|
||||
set_initial_gvn(&gvn);
|
||||
|
||||
if (_do_escape_analysis)
|
||||
_congraph = new ConnectionGraph(this);
|
||||
|
||||
{ // Scope for timing the parser
|
||||
TracePhase t3("parse", &_t_parser, true);
|
||||
|
||||
@ -581,6 +573,8 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
|
||||
NOT_PRODUCT( verify_graph_edges(); )
|
||||
|
||||
// Perform escape analysis
|
||||
if (_do_escape_analysis)
|
||||
_congraph = new ConnectionGraph(this);
|
||||
if (_congraph != NULL) {
|
||||
NOT_PRODUCT( TracePhase t2("escapeAnalysis", &_t_escapeAnalysis, TimeCompiler); )
|
||||
_congraph->compute_escape();
|
||||
|
@ -485,7 +485,6 @@ class Compile : public Phase {
|
||||
PhaseGVN* initial_gvn() { return _initial_gvn; }
|
||||
Unique_Node_List* for_igvn() { return _for_igvn; }
|
||||
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_for_igvn(Unique_Node_List *for_igvn) { _for_igvn = for_igvn; }
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -25,14 +25,15 @@
|
||||
//
|
||||
// Adaptation for C2 of the escape analysis algorithm described in:
|
||||
//
|
||||
// [Choi99] Jong-Deok Shoi, Manish Gupta, Mauricio Seffano, Vugranam C. Sreedhar,
|
||||
// Sam Midkiff, "Escape Analysis for Java", Procedings of ACM SIGPLAN
|
||||
// OOPSLA Conference, November 1, 1999
|
||||
// [Choi99] Jong-Deok Shoi, Manish Gupta, Mauricio Seffano,
|
||||
// Vugranam C. Sreedhar, Sam Midkiff,
|
||||
// "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 analysis requires construction of a "connection graph" (CG) for the method being
|
||||
// analyzed. The nodes of the connection graph are:
|
||||
// The analysis requires construction of a "connection graph" (CG) for
|
||||
// the method being analyzed. The nodes of the connection graph are:
|
||||
//
|
||||
// - Java objects (JO)
|
||||
// - Local variables (LV)
|
||||
@ -40,47 +41,51 @@
|
||||
//
|
||||
// The CG contains 3 types of edges:
|
||||
//
|
||||
// - PointsTo (-P>) {LV,OF} to JO
|
||||
// - Deferred (-D>) from {LV, OF} to {LV, OF}
|
||||
// - PointsTo (-P>) {LV, OF} to JO
|
||||
// - Deferred (-D>) from {LV, OF} to {LV, OF}
|
||||
// - Field (-F>) from JO to OF
|
||||
//
|
||||
// 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
|
||||
// point to.
|
||||
// PointsTo(n) - n is any CG node, it returns the set of JO that n could
|
||||
// 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
|
||||
//
|
||||
// (1) p = new T() LV -P> JO
|
||||
// (2) p = q LV -D> LV
|
||||
// (3) p.f = q JO -F> OF, OF -D> LV
|
||||
// (4) p = q.f JO -F> OF, LV -D> OF
|
||||
// (1) p = new T() LV -P> JO
|
||||
// (2) p = q LV -D> LV
|
||||
// (3) p.f = q JO -F> OF, OF -D> LV
|
||||
// (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
|
||||
// construct a local variable containing a reference to the static memory.
|
||||
// In all these cases, p and q are local variables. For static field
|
||||
// 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
|
||||
// the connection graph, the following IR nodes are treated as local variables:
|
||||
// Phi (pointer values)
|
||||
// LoadP
|
||||
// Proj (value returned from callnodes including allocations)
|
||||
// CheckCastPP
|
||||
// Proj#5 (value returned from callnodes including allocations)
|
||||
// CheckCastPP, CastPP
|
||||
//
|
||||
// The LoadP, Proj and CheckCastPP behave like variables assigned to only once. Only
|
||||
// a Phi can have multiple assignments. Each input to a Phi is treated
|
||||
// The LoadP, Proj and CheckCastPP behave like variables assigned to only once.
|
||||
// Only a Phi can have multiple assignments. Each input to a Phi is treated
|
||||
// as an assignment to it.
|
||||
//
|
||||
// The following note types are JavaObject:
|
||||
// The following node types are JavaObject:
|
||||
//
|
||||
// top()
|
||||
// Allocate
|
||||
// AllocateArray
|
||||
// Parm (for incoming arguments)
|
||||
// CastX2P ("unsafe" operations)
|
||||
// CreateEx
|
||||
// ConP
|
||||
// LoadKlass
|
||||
// ThreadLocal
|
||||
//
|
||||
// AddP nodes are fields.
|
||||
//
|
||||
@ -89,7 +94,7 @@
|
||||
// source. This results in a graph with no deferred edges, only:
|
||||
//
|
||||
// LV -P> JO
|
||||
// OF -P> JO
|
||||
// OF -P> JO (the object whose oop is stored in the field)
|
||||
// JO -F> OF
|
||||
//
|
||||
// Then, for each node which is GlobalEscape, anything it could point to
|
||||
@ -110,17 +115,18 @@ class PointsToNode {
|
||||
friend class ConnectionGraph;
|
||||
public:
|
||||
typedef enum {
|
||||
UnknownType = 0,
|
||||
JavaObject = 1,
|
||||
LocalVar = 2,
|
||||
Field = 3
|
||||
UnknownType = 0,
|
||||
JavaObject = 1,
|
||||
LocalVar = 2,
|
||||
Field = 3
|
||||
} NodeType;
|
||||
|
||||
typedef enum {
|
||||
UnknownEscape = 0,
|
||||
NoEscape = 1,
|
||||
ArgEscape = 2,
|
||||
GlobalEscape = 3
|
||||
NoEscape = 1, // A scalar replaceable object with unique type.
|
||||
ArgEscape = 2, // An object passed as argument or referenced by
|
||||
// argument (and not globally escape during call).
|
||||
GlobalEscape = 3 // An object escapes the method and thread.
|
||||
} EscapeState;
|
||||
|
||||
typedef enum {
|
||||
@ -140,18 +146,24 @@ private:
|
||||
|
||||
NodeType _type;
|
||||
EscapeState _escape;
|
||||
GrowableArray<uint>* _edges; // outgoing edges
|
||||
int _offset; // for fields
|
||||
GrowableArray<uint>* _edges; // outgoing edges
|
||||
|
||||
bool _unique_type; // For allocated objects, this node may be a unique type
|
||||
public:
|
||||
Node* _node; // Ideal node corresponding to this PointsTo node
|
||||
int _inputs_processed; // the number of Phi inputs that have been processed so far
|
||||
bool _hidden_alias; // this node is an argument to a function which may return it
|
||||
// creating a hidden alias
|
||||
Node* _node; // Ideal node corresponding to this PointsTo node.
|
||||
int _offset; // Object fields offsets.
|
||||
bool _scalar_replaceable;// Not escaped object could be replaced with scalar
|
||||
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; }
|
||||
NodeType node_type() const { return _type;}
|
||||
@ -182,22 +194,28 @@ public:
|
||||
|
||||
class ConnectionGraph: public ResourceObj {
|
||||
private:
|
||||
enum {
|
||||
INITIAL_NODE_COUNT = 100 // initial size of _nodes array
|
||||
};
|
||||
GrowableArray<PointsToNode>* _nodes; // Connection graph nodes indexed
|
||||
// by ideal node index.
|
||||
|
||||
Unique_Node_List _delayed_worklist; // Nodes to be processed before
|
||||
// the call build_connection_graph().
|
||||
|
||||
GrowableArray<PointsToNode>* _nodes; // connection graph nodes Indexed by ideal
|
||||
// node index
|
||||
Unique_Node_List _deferred; // Phi's to be processed after parsing
|
||||
VectorSet _processed; // records which nodes have been processed
|
||||
bool _collecting; // indicates whether escape information is
|
||||
// still being collected. If false, no new
|
||||
// nodes will be processed
|
||||
uint _phantom_object; // index of globally escaping object that
|
||||
// pointer values loaded from a field which
|
||||
// has not been set are assumed to point to
|
||||
Compile * _compile; // Compile object for current compilation
|
||||
VectorSet _processed; // Records which nodes have been
|
||||
// processed.
|
||||
|
||||
bool _collecting; // Indicates whether escape information
|
||||
// is still being collected. If false,
|
||||
// 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
|
||||
// that pointer values loaded from
|
||||
// a field which has not been set
|
||||
// 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
|
||||
PointsToNode *ptnode_adr(uint idx) {
|
||||
@ -208,8 +226,11 @@ private:
|
||||
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
|
||||
int type_to_offset(const Type *t);
|
||||
int address_offset(Node* adr, PhaseTransform *phase);
|
||||
|
||||
// compute the escape state for arguments to a call
|
||||
void process_call_arguments(CallNode *call, PhaseTransform *phase);
|
||||
@ -217,12 +238,11 @@ private:
|
||||
// compute the escape state for the return value of a call
|
||||
void process_call_result(ProjNode *resproj, PhaseTransform *phase);
|
||||
|
||||
// compute the escape state of a Phi. This may be called multiple
|
||||
// times as new inputs are added to the Phi.
|
||||
void process_phi_escape(PhiNode *phi, PhaseTransform *phase);
|
||||
// Populate Connection Graph with Ideal nodes.
|
||||
void record_for_escape_analysis(Node *n, PhaseTransform *phase);
|
||||
|
||||
// compute the escape state of an ideal node.
|
||||
void record_escape_work(Node *n, PhaseTransform *phase);
|
||||
// Build Connection Graph and set nodes escape state.
|
||||
void build_connection_graph(Node *n, PhaseTransform *phase);
|
||||
|
||||
// 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
|
||||
@ -241,8 +261,8 @@ private:
|
||||
// a pointsto edge is added if it is a JavaObject
|
||||
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
|
||||
// matches "offset"
|
||||
// Add a deferred edge from node given by "from_i" to any field
|
||||
// of adr_i whose offset matches "offset"
|
||||
void add_deferred_edge_to_fields(uint from_i, uint adr, int offs);
|
||||
|
||||
|
||||
@ -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 *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_inst_mem(Node *mem, int alias_idx,GrowableArray<PhiNode *> &orig_phi_worklist, PhaseGVN *igvn);
|
||||
|
||||
// Propagate unique types created for unescaped allocated objects
|
||||
// through the graph
|
||||
void split_unique_types(GrowableArray<Node *> &alloc_worklist);
|
||||
@ -285,26 +307,24 @@ private:
|
||||
// Set the escape state of a node
|
||||
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.
|
||||
Compile *C() const { return _compile; }
|
||||
|
||||
public:
|
||||
ConnectionGraph(Compile *C);
|
||||
|
||||
// record a Phi for later processing.
|
||||
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
|
||||
// Compute the escape information
|
||||
void compute_escape();
|
||||
|
||||
// escape state of a node
|
||||
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) {
|
||||
if (_collecting)
|
||||
|
@ -812,8 +812,7 @@ int Node::disconnect_inputs(Node *n) {
|
||||
Node* Node::uncast() const {
|
||||
// Should be inline:
|
||||
//return is_ConstraintCast() ? uncast_helper(this) : (Node*) this;
|
||||
if (is_ConstraintCast() ||
|
||||
(is_Type() && req() == 2 && Opcode() == Op_CheckCastPP))
|
||||
if (is_ConstraintCast() || is_CheckCastPP())
|
||||
return uncast_helper(this);
|
||||
else
|
||||
return (Node*) this;
|
||||
@ -827,7 +826,7 @@ Node* Node::uncast_helper(const Node* p) {
|
||||
break;
|
||||
} else if (p->is_ConstraintCast()) {
|
||||
p = p->in(1);
|
||||
} else if (p->is_Type() && p->Opcode() == Op_CheckCastPP) {
|
||||
} else if (p->is_CheckCastPP()) {
|
||||
p = p->in(1);
|
||||
} else {
|
||||
break;
|
||||
|
@ -1328,7 +1328,6 @@ public:
|
||||
// Inline definition of Compile::record_for_igvn must be deferred to this point.
|
||||
inline void Compile::record_for_igvn(Node* n) {
|
||||
_for_igvn->push(n);
|
||||
record_for_escape_analysis(n);
|
||||
}
|
||||
|
||||
//------------------------------Node_Stack-------------------------------------
|
||||
|
@ -587,11 +587,6 @@ ConNode* PhaseValues::uncached_makecon(const Type *t) {
|
||||
Node_Notes* loc = C->locate_node_notes(nna, x->_idx, true);
|
||||
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 {
|
||||
x->destruct(); // Hit, destroy duplicate constant
|
||||
x = k; // use existing constant
|
||||
@ -714,12 +709,6 @@ Node *PhaseGVN::transform_no_reclaim( Node *n ) {
|
||||
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 k;
|
||||
}
|
||||
@ -1245,7 +1234,7 @@ void PhaseIterGVN::add_users_to_worklist( Node *n ) {
|
||||
|
||||
uint use_op = use->Opcode();
|
||||
// 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++) {
|
||||
Node* u = use->fast_out(i2);
|
||||
if (u->is_Phi())
|
||||
|
@ -1276,6 +1276,9 @@ void Arguments::set_aggressive_opts_flags() {
|
||||
sprintf(buffer, "java.lang.Integer.IntegerCache.high=%d", AutoBoxCacheMax);
|
||||
add_property(buffer);
|
||||
}
|
||||
if (AggressiveOpts && FLAG_IS_DEFAULT(DoEscapeAnalysis)) {
|
||||
FLAG_SET_DEFAULT(DoEscapeAnalysis, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (AggressiveOpts) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user