提交 1b653533 编写于 作者: K kvn

7013538: Java memory leak with escape analysis

Summary: Don't allocate VectorSet iterator on C heap. Reuse resource storage in EA.
Reviewed-by: never
上级 5bceb250
/* /*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -350,28 +350,11 @@ int VectorSet::hash() const ...@@ -350,28 +350,11 @@ int VectorSet::hash() const
return (int)_xor; return (int)_xor;
} }
//------------------------------iterate----------------------------------------
SetI_ *VectorSet::iterate(uint &elem) const
{
VSetI_ *foo = (new(ResourceObj::C_HEAP) VSetI_(this));
elem = foo->next();
return foo;
}
//============================================================================= //=============================================================================
//------------------------------VSetI_-----------------------------------------
// Initialize the innards of a VectorSet iterator
VSetI_::VSetI_( const VectorSet *vset ) : s(vset)
{
i = (uint)-1L;
j = (uint)-1L;
mask = (unsigned)(1L<<31);
}
//------------------------------next------------------------------------------- //------------------------------next-------------------------------------------
// Find and return the next element of a vector set, or return garbage and // Find and return the next element of a vector set, or return garbage and
// make "VSetI_::test()" fail. // make "VectorSetI::test()" fail.
uint VSetI_::next(void) uint VectorSetI::next(void)
{ {
j++; // Next element in word j++; // Next element in word
mask = (mask & max_jint) << 1;// Next bit in word mask = (mask & max_jint) << 1;// Next bit in word
......
/* /*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -98,6 +98,9 @@ public: ...@@ -98,6 +98,9 @@ public:
uint Size(void) const; // Number of elements in the Set. uint Size(void) const; // Number of elements in the Set.
void Sort(void); // Sort before iterating void Sort(void); // Sort before iterating
int hash() const; // Hash function int hash() const; // Hash function
void Reset(void) { // Reset a set
memset( data, 0, size*sizeof(uint32) );
}
/* Removed for MCC BUG /* Removed for MCC BUG
operator const VectorSet* (void) const { return this; } */ operator const VectorSet* (void) const { return this; } */
...@@ -148,8 +151,7 @@ public: ...@@ -148,8 +151,7 @@ public:
private: private:
friend class VSetI_; SetI_ *iterate(uint&) const { ShouldNotCallThis(); return NULL; } // Removed
SetI_ *iterate(uint&) const;
}; };
//------------------------------Iteration-------------------------------------- //------------------------------Iteration--------------------------------------
...@@ -158,22 +160,26 @@ private: ...@@ -158,22 +160,26 @@ private:
// or may not be iterated over; untouched elements will be affected once. // or may not be iterated over; untouched elements will be affected once.
// Usage: for( VectorSetI i(s); i.test(); i++ ) { body = i.elem; } // Usage: for( VectorSetI i(s); i.test(); i++ ) { body = i.elem; }
class VSetI_ : public SetI_ { class VectorSetI : public StackObj {
friend class VectorSet; friend class VectorSet;
friend class VectorSetI;
const VectorSet *s; const VectorSet *s;
uint i, j; uint i, j;
uint32 mask; uint32 mask;
VSetI_(const VectorSet *vset);
uint next(void); uint next(void);
int test(void) { return i < s->size; }
};
class VectorSetI : public SetI {
public: public:
VectorSetI( const VectorSet *s ) : SetI(s) { } uint elem; // The publically accessible element
void operator ++(void) { elem = ((VSetI_*)impl)->next(); }
int test(void) { return ((VSetI_*)impl)->test(); } VectorSetI( const VectorSet *vset ) :
s(vset),
i((uint)-1L),
j((uint)-1L),
mask((unsigned)(1L<<31)) {
elem = next();
}
void operator ++(void) { elem = next(); }
int test(void) { return i < s->size; }
}; };
#endif // SHARE_VM_LIBADT_VECTSET_HPP #endif // SHARE_VM_LIBADT_VECTSET_HPP
/* /*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -93,6 +93,9 @@ void PointsToNode::dump(bool print_state) const { ...@@ -93,6 +93,9 @@ void PointsToNode::dump(bool print_state) const {
ConnectionGraph::ConnectionGraph(Compile * C, PhaseIterGVN *igvn) : ConnectionGraph::ConnectionGraph(Compile * C, PhaseIterGVN *igvn) :
_nodes(C->comp_arena(), C->unique(), C->unique(), PointsToNode()), _nodes(C->comp_arena(), C->unique(), C->unique(), PointsToNode()),
_processed(C->comp_arena()), _processed(C->comp_arena()),
pt_ptset(C->comp_arena()),
pt_visited(C->comp_arena()),
pt_worklist(C->comp_arena(), 4, 0, 0),
_collecting(true), _collecting(true),
_progress(false), _progress(false),
_compile(C), _compile(C),
...@@ -220,9 +223,7 @@ PointsToNode::EscapeState ConnectionGraph::escape_state(Node *n) { ...@@ -220,9 +223,7 @@ PointsToNode::EscapeState ConnectionGraph::escape_state(Node *n) {
PointsToNode::EscapeState orig_es = es; PointsToNode::EscapeState orig_es = es;
// compute max escape state of anything this node could point to // compute max escape state of anything this node could point to
VectorSet ptset(Thread::current()->resource_area()); for(VectorSetI i(PointsTo(n)); i.test() && es != PointsToNode::GlobalEscape; ++i) {
PointsTo(ptset, n);
for(VectorSetI i(&ptset); i.test() && es != PointsToNode::GlobalEscape; ++i) {
uint pt = i.elem; uint pt = i.elem;
PointsToNode::EscapeState pes = ptnode_adr(pt)->escape_state(); PointsToNode::EscapeState pes = ptnode_adr(pt)->escape_state();
if (pes > es) if (pes > es)
...@@ -236,9 +237,10 @@ PointsToNode::EscapeState ConnectionGraph::escape_state(Node *n) { ...@@ -236,9 +237,10 @@ PointsToNode::EscapeState ConnectionGraph::escape_state(Node *n) {
return es; return es;
} }
void ConnectionGraph::PointsTo(VectorSet &ptset, Node * n) { VectorSet* ConnectionGraph::PointsTo(Node * n) {
VectorSet visited(Thread::current()->resource_area()); pt_ptset.Reset();
GrowableArray<uint> worklist; pt_visited.Reset();
pt_worklist.clear();
#ifdef ASSERT #ifdef ASSERT
Node *orig_n = n; Node *orig_n = n;
...@@ -249,8 +251,8 @@ void ConnectionGraph::PointsTo(VectorSet &ptset, Node * n) { ...@@ -249,8 +251,8 @@ void ConnectionGraph::PointsTo(VectorSet &ptset, Node * n) {
// If we have a JavaObject, return just that object // If we have a JavaObject, return just that object
if (npt->node_type() == PointsToNode::JavaObject) { if (npt->node_type() == PointsToNode::JavaObject) {
ptset.set(n->_idx); pt_ptset.set(n->_idx);
return; return &pt_ptset;
} }
#ifdef ASSERT #ifdef ASSERT
if (npt->_node == NULL) { if (npt->_node == NULL) {
...@@ -260,10 +262,10 @@ void ConnectionGraph::PointsTo(VectorSet &ptset, Node * n) { ...@@ -260,10 +262,10 @@ void ConnectionGraph::PointsTo(VectorSet &ptset, Node * n) {
assert(npt->_node != NULL, "unregistered node"); assert(npt->_node != NULL, "unregistered node");
} }
#endif #endif
worklist.push(n->_idx); pt_worklist.push(n->_idx);
while(worklist.length() > 0) { while(pt_worklist.length() > 0) {
int ni = worklist.pop(); int ni = pt_worklist.pop();
if (visited.test_set(ni)) if (pt_visited.test_set(ni))
continue; continue;
PointsToNode* pn = ptnode_adr(ni); PointsToNode* pn = ptnode_adr(ni);
...@@ -276,10 +278,10 @@ void ConnectionGraph::PointsTo(VectorSet &ptset, Node * n) { ...@@ -276,10 +278,10 @@ void ConnectionGraph::PointsTo(VectorSet &ptset, Node * n) {
uint etgt = pn->edge_target(e); uint etgt = pn->edge_target(e);
PointsToNode::EdgeType et = pn->edge_type(e); PointsToNode::EdgeType et = pn->edge_type(e);
if (et == PointsToNode::PointsToEdge) { if (et == PointsToNode::PointsToEdge) {
ptset.set(etgt); pt_ptset.set(etgt);
edges_processed++; edges_processed++;
} else if (et == PointsToNode::DeferredEdge) { } else if (et == PointsToNode::DeferredEdge) {
worklist.push(etgt); pt_worklist.push(etgt);
edges_processed++; edges_processed++;
} else { } else {
assert(false,"neither PointsToEdge or DeferredEdge"); assert(false,"neither PointsToEdge or DeferredEdge");
...@@ -288,16 +290,17 @@ void ConnectionGraph::PointsTo(VectorSet &ptset, Node * n) { ...@@ -288,16 +290,17 @@ void ConnectionGraph::PointsTo(VectorSet &ptset, Node * n) {
if (edges_processed == 0) { if (edges_processed == 0) {
// no deferred or pointsto edges found. Assume the value was set // no deferred or pointsto edges found. Assume the value was set
// outside this method. Add the phantom object to the pointsto set. // outside this method. Add the phantom object to the pointsto set.
ptset.set(_phantom_object); pt_ptset.set(_phantom_object);
} }
} }
return &pt_ptset;
} }
void ConnectionGraph::remove_deferred(uint ni, GrowableArray<uint>* deferred_edges, VectorSet* visited) { void ConnectionGraph::remove_deferred(uint ni, GrowableArray<uint>* deferred_edges, VectorSet* visited) {
// This method is most expensive during ConnectionGraph construction. // This method is most expensive during ConnectionGraph construction.
// Reuse vectorSet and an additional growable array for deferred edges. // Reuse vectorSet and an additional growable array for deferred edges.
deferred_edges->clear(); deferred_edges->clear();
visited->Clear(); visited->Reset();
visited->set(ni); visited->set(ni);
PointsToNode *ptn = ptnode_adr(ni); PointsToNode *ptn = ptnode_adr(ni);
...@@ -1009,7 +1012,6 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist) ...@@ -1009,7 +1012,6 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist)
uint new_index_start = (uint) _compile->num_alias_types(); uint new_index_start = (uint) _compile->num_alias_types();
Arena* arena = Thread::current()->resource_area(); Arena* arena = Thread::current()->resource_area();
VectorSet visited(arena); VectorSet visited(arena);
VectorSet ptset(arena);
// Phase 1: Process possible allocations from alloc_worklist. // Phase 1: Process possible allocations from alloc_worklist.
...@@ -1137,10 +1139,9 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist) ...@@ -1137,10 +1139,9 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist)
} }
} }
} else if (n->is_AddP()) { } else if (n->is_AddP()) {
ptset.Clear(); VectorSet* ptset = PointsTo(get_addp_base(n));
PointsTo(ptset, get_addp_base(n)); assert(ptset->Size() == 1, "AddP address is unique");
assert(ptset.Size() == 1, "AddP address is unique"); uint elem = ptset->getelem(); // Allocation node's index
uint elem = ptset.getelem(); // Allocation node's index
if (elem == _phantom_object) { if (elem == _phantom_object) {
assert(false, "escaped allocation"); assert(false, "escaped allocation");
continue; // Assume the value was set outside this method. continue; // Assume the value was set outside this method.
...@@ -1157,10 +1158,9 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist) ...@@ -1157,10 +1158,9 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist)
assert(n->is_Phi(), "loops only through Phi's"); assert(n->is_Phi(), "loops only through Phi's");
continue; // already processed continue; // already processed
} }
ptset.Clear(); VectorSet* ptset = PointsTo(n);
PointsTo(ptset, n); if (ptset->Size() == 1) {
if (ptset.Size() == 1) { uint elem = ptset->getelem(); // Allocation node's index
uint elem = ptset.getelem(); // Allocation node's index
if (elem == _phantom_object) { if (elem == _phantom_object) {
assert(false, "escaped allocation"); assert(false, "escaped allocation");
continue; // Assume the value was set outside this method. continue; // Assume the value was set outside this method.
...@@ -1434,7 +1434,7 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist) ...@@ -1434,7 +1434,7 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist)
// Update the memory inputs of MemNodes with the value we computed // Update the memory inputs of MemNodes with the value we computed
// in Phase 2 and move stores memory users to corresponding memory slices. // in Phase 2 and move stores memory users to corresponding memory slices.
#ifdef ASSERT #ifdef ASSERT
visited.Clear(); visited.Reset();
Node_Stack old_mems(arena, _compile->unique() >> 2); Node_Stack old_mems(arena, _compile->unique() >> 2);
#endif #endif
for (uint i = 0; i < nodes_size(); i++) { for (uint i = 0; i < nodes_size(); i++) {
...@@ -1640,7 +1640,6 @@ bool ConnectionGraph::compute_escape() { ...@@ -1640,7 +1640,6 @@ bool ConnectionGraph::compute_escape() {
#undef CG_BUILD_ITER_LIMIT #undef CG_BUILD_ITER_LIMIT
Arena* arena = Thread::current()->resource_area(); Arena* arena = Thread::current()->resource_area();
VectorSet ptset(arena);
VectorSet visited(arena); VectorSet visited(arena);
worklist.clear(); worklist.clear();
...@@ -1657,7 +1656,7 @@ bool ConnectionGraph::compute_escape() { ...@@ -1657,7 +1656,7 @@ bool ConnectionGraph::compute_escape() {
if (n->is_AddP()) { if (n->is_AddP()) {
// Search for objects which are not scalar replaceable // Search for objects which are not scalar replaceable
// and adjust their escape state. // and adjust their escape state.
verify_escape_state(ni, ptset, igvn); adjust_escape_state(ni, igvn);
} }
} }
} }
...@@ -1776,8 +1775,8 @@ bool ConnectionGraph::compute_escape() { ...@@ -1776,8 +1775,8 @@ bool ConnectionGraph::compute_escape() {
return has_non_escaping_obj; return has_non_escaping_obj;
} }
// Search for objects which are not scalar replaceable. // Adjust escape state after Connection Graph is built.
void ConnectionGraph::verify_escape_state(int nidx, VectorSet& ptset, PhaseTransform* phase) { void ConnectionGraph::adjust_escape_state(int nidx, PhaseTransform* phase) {
PointsToNode* ptn = ptnode_adr(nidx); PointsToNode* ptn = ptnode_adr(nidx);
Node* n = ptn->_node; Node* n = ptn->_node;
assert(n->is_AddP(), "Should be called for AddP nodes only"); assert(n->is_AddP(), "Should be called for AddP nodes only");
...@@ -1792,9 +1791,8 @@ void ConnectionGraph::verify_escape_state(int nidx, VectorSet& ptset, PhaseTrans ...@@ -1792,9 +1791,8 @@ void ConnectionGraph::verify_escape_state(int nidx, VectorSet& ptset, PhaseTrans
int offset = ptn->offset(); int offset = ptn->offset();
Node* base = get_addp_base(n); Node* base = get_addp_base(n);
ptset.Clear(); VectorSet* ptset = PointsTo(base);
PointsTo(ptset, base); int ptset_size = ptset->Size();
int ptset_size = ptset.Size();
// Check if a oop field's initializing value is recorded and add // Check if a oop field's initializing value is recorded and add
// a corresponding NULL field's value if it is not recorded. // a corresponding NULL field's value if it is not recorded.
...@@ -1814,7 +1812,7 @@ void ConnectionGraph::verify_escape_state(int nidx, VectorSet& ptset, PhaseTrans ...@@ -1814,7 +1812,7 @@ void ConnectionGraph::verify_escape_state(int nidx, VectorSet& ptset, PhaseTrans
// Do a simple control flow analysis to distinguish above cases. // Do a simple control flow analysis to distinguish above cases.
// //
if (offset != Type::OffsetBot && ptset_size == 1) { if (offset != Type::OffsetBot && ptset_size == 1) {
uint elem = ptset.getelem(); // Allocation node's index uint elem = ptset->getelem(); // Allocation node's index
// It does not matter if it is not Allocation node since // It does not matter if it is not Allocation node since
// only non-escaping allocations are scalar replaced. // only non-escaping allocations are scalar replaced.
if (ptnode_adr(elem)->_node->is_Allocate() && if (ptnode_adr(elem)->_node->is_Allocate() &&
...@@ -1913,7 +1911,7 @@ void ConnectionGraph::verify_escape_state(int nidx, VectorSet& ptset, PhaseTrans ...@@ -1913,7 +1911,7 @@ void ConnectionGraph::verify_escape_state(int nidx, VectorSet& ptset, PhaseTrans
// //
if (ptset_size > 1 || ptset_size != 0 && if (ptset_size > 1 || ptset_size != 0 &&
(has_LoadStore || offset == Type::OffsetBot)) { (has_LoadStore || offset == Type::OffsetBot)) {
for( VectorSetI j(&ptset); j.test(); ++j ) { for( VectorSetI j(ptset); j.test(); ++j ) {
set_escape_state(j.elem, PointsToNode::ArgEscape); set_escape_state(j.elem, PointsToNode::ArgEscape);
ptnode_adr(j.elem)->_scalar_replaceable = false; ptnode_adr(j.elem)->_scalar_replaceable = false;
} }
...@@ -1937,7 +1935,6 @@ void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *pha ...@@ -1937,7 +1935,6 @@ void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *pha
// Stub calls, objects do not escape but they are not scale replaceable. // Stub calls, objects do not escape but they are not scale replaceable.
// Adjust escape state for outgoing arguments. // Adjust escape state for outgoing arguments.
const TypeTuple * d = call->tf()->domain(); const TypeTuple * d = call->tf()->domain();
VectorSet ptset(Thread::current()->resource_area());
for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
const Type* at = d->field_at(i); const Type* at = d->field_at(i);
Node *arg = call->in(i)->uncast(); Node *arg = call->in(i)->uncast();
...@@ -1970,9 +1967,7 @@ void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *pha ...@@ -1970,9 +1967,7 @@ void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *pha
// //
arg = get_addp_base(arg); arg = get_addp_base(arg);
} }
ptset.Clear(); for( VectorSetI j(PointsTo(arg)); j.test(); ++j ) {
PointsTo(ptset, arg);
for( VectorSetI j(&ptset); j.test(); ++j ) {
uint pt = j.elem; uint pt = j.elem;
set_escape_state(pt, PointsToNode::ArgEscape); set_escape_state(pt, PointsToNode::ArgEscape);
} }
...@@ -1990,7 +1985,6 @@ void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *pha ...@@ -1990,7 +1985,6 @@ void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *pha
// fall-through if not a Java method or no analyzer information // fall-through if not a Java method or no analyzer information
if (call_analyzer != NULL) { if (call_analyzer != NULL) {
const TypeTuple * d = call->tf()->domain(); const TypeTuple * d = call->tf()->domain();
VectorSet ptset(Thread::current()->resource_area());
bool copy_dependencies = false; bool copy_dependencies = false;
for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
const Type* at = d->field_at(i); const Type* at = d->field_at(i);
...@@ -2015,9 +2009,7 @@ void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *pha ...@@ -2015,9 +2009,7 @@ void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *pha
copy_dependencies = true; copy_dependencies = true;
} }
ptset.Clear(); for( VectorSetI j(PointsTo(arg)); j.test(); ++j ) {
PointsTo(ptset, arg);
for( VectorSetI j(&ptset); j.test(); ++j ) {
uint pt = j.elem; uint pt = j.elem;
if (global_escapes) { if (global_escapes) {
//The argument global escapes, mark everything it could point to //The argument global escapes, mark everything it could point to
...@@ -2045,15 +2037,12 @@ void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *pha ...@@ -2045,15 +2037,12 @@ void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *pha
{ {
// adjust escape state for outgoing arguments // adjust escape state for outgoing arguments
const TypeTuple * d = call->tf()->domain(); const TypeTuple * d = call->tf()->domain();
VectorSet ptset(Thread::current()->resource_area());
for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
const Type* at = d->field_at(i); const Type* at = d->field_at(i);
if (at->isa_oopptr() != NULL) { if (at->isa_oopptr() != NULL) {
Node *arg = call->in(i)->uncast(); Node *arg = call->in(i)->uncast();
set_escape_state(arg->_idx, PointsToNode::GlobalEscape); set_escape_state(arg->_idx, PointsToNode::GlobalEscape);
ptset.Clear(); for( VectorSetI j(PointsTo(arg)); j.test(); ++j ) {
PointsTo(ptset, arg);
for( VectorSetI j(&ptset); j.test(); ++j ) {
uint pt = j.elem; uint pt = j.elem;
set_escape_state(pt, PointsToNode::GlobalEscape); set_escape_state(pt, PointsToNode::GlobalEscape);
} }
...@@ -2515,9 +2504,7 @@ void ConnectionGraph::build_connection_graph(Node *n, PhaseTransform *phase) { ...@@ -2515,9 +2504,7 @@ void ConnectionGraph::build_connection_graph(Node *n, PhaseTransform *phase) {
{ {
Node *base = get_addp_base(n); Node *base = get_addp_base(n);
// Create a field edge to this node from everything base could point to. // Create a field edge to this node from everything base could point to.
VectorSet ptset(Thread::current()->resource_area()); for( VectorSetI i(PointsTo(base)); i.test(); ++i ) {
PointsTo(ptset, base);
for( VectorSetI i(&ptset); i.test(); ++i ) {
uint pt = i.elem; uint pt = i.elem;
add_field_edge(pt, n_idx, address_offset(n, phase)); add_field_edge(pt, n_idx, address_offset(n, phase));
} }
...@@ -2583,10 +2570,8 @@ void ConnectionGraph::build_connection_graph(Node *n, PhaseTransform *phase) { ...@@ -2583,10 +2570,8 @@ void ConnectionGraph::build_connection_graph(Node *n, PhaseTransform *phase) {
// For everything "adr_base" could point to, create a deferred edge from // For everything "adr_base" could point to, create a deferred edge from
// this node to each field with the same offset. // this node to each field with the same offset.
VectorSet ptset(Thread::current()->resource_area());
PointsTo(ptset, adr_base);
int offset = address_offset(adr, phase); int offset = address_offset(adr, phase);
for( VectorSetI i(&ptset); i.test(); ++i ) { for( VectorSetI i(PointsTo(adr_base)); i.test(); ++i ) {
uint pt = i.elem; uint pt = i.elem;
add_deferred_edge_to_fields(n_idx, pt, offset); add_deferred_edge_to_fields(n_idx, pt, offset);
} }
...@@ -2676,9 +2661,7 @@ void ConnectionGraph::build_connection_graph(Node *n, PhaseTransform *phase) { ...@@ -2676,9 +2661,7 @@ void ConnectionGraph::build_connection_graph(Node *n, PhaseTransform *phase) {
Node *val = n->in(MemNode::ValueIn)->uncast(); Node *val = n->in(MemNode::ValueIn)->uncast();
// For everything "adr_base" could point to, create a deferred edge // For everything "adr_base" could point to, create a deferred edge
// to "val" from each field with the same offset. // to "val" from each field with the same offset.
VectorSet ptset(Thread::current()->resource_area()); for( VectorSetI i(PointsTo(adr_base)); i.test(); ++i ) {
PointsTo(ptset, adr_base);
for( VectorSetI i(&ptset); i.test(); ++i ) {
uint pt = i.elem; uint pt = i.elem;
add_edge_from_fields(pt, val->_idx, address_offset(adr, phase)); add_edge_from_fields(pt, val->_idx, address_offset(adr, phase));
} }
......
/* /*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -268,7 +268,12 @@ private: ...@@ -268,7 +268,12 @@ private:
// 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
// Phi's encountered to get (re)processed (which requires "phase".) // Phi's encountered to get (re)processed (which requires "phase".)
void PointsTo(VectorSet &ptset, Node * n); VectorSet* PointsTo(Node * n);
// Reused structures for PointsTo().
VectorSet pt_ptset;
VectorSet pt_visited;
GrowableArray<uint> pt_worklist;
// Edge manipulation. The "from_i" and "to_i" arguments are the // Edge manipulation. The "from_i" and "to_i" arguments are the
// node indices of the source and destination of the edge // node indices of the source and destination of the edge
...@@ -334,8 +339,11 @@ private: ...@@ -334,8 +339,11 @@ 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);
// Search for objects which are not scalar replaceable. // Adjust escape state after Connection Graph is built.
void verify_escape_state(int nidx, VectorSet& ptset, PhaseTransform* phase); void adjust_escape_state(int nidx, PhaseTransform* phase);
// Compute the escape information
bool compute_escape();
public: public:
ConnectionGraph(Compile *C, PhaseIterGVN *igvn); ConnectionGraph(Compile *C, PhaseIterGVN *igvn);
...@@ -346,9 +354,6 @@ public: ...@@ -346,9 +354,6 @@ public:
// Perform escape analysis // Perform escape analysis
static void do_analysis(Compile *C, PhaseIterGVN *igvn); static void do_analysis(Compile *C, PhaseIterGVN *igvn);
// Compute the escape information
bool compute_escape();
// escape state of a node // escape state of a node
PointsToNode::EscapeState escape_state(Node *n); PointsToNode::EscapeState escape_state(Node *n);
......
/* /*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -99,16 +99,18 @@ void Phase::print_timers() { ...@@ -99,16 +99,18 @@ void Phase::print_timers() {
tty->print_cr (" stub compilation : %3.3f sec.", Phase::_t_stubCompilation.seconds()); tty->print_cr (" stub compilation : %3.3f sec.", Phase::_t_stubCompilation.seconds());
tty->print_cr (" Phases:"); tty->print_cr (" Phases:");
tty->print_cr (" parse : %3.3f sec", Phase::_t_parser.seconds()); tty->print_cr (" parse : %3.3f sec", Phase::_t_parser.seconds());
if (DoEscapeAnalysis) {
tty->print_cr (" escape analysis : %3.3f sec", Phase::_t_escapeAnalysis.seconds());
}
tty->print_cr (" optimizer : %3.3f sec", Phase::_t_optimizer.seconds()); tty->print_cr (" optimizer : %3.3f sec", Phase::_t_optimizer.seconds());
if( Verbose || WizardMode ) { if( Verbose || WizardMode ) {
if (DoEscapeAnalysis) {
// EA is part of Optimizer.
tty->print_cr (" escape analysis: %3.3f sec", Phase::_t_escapeAnalysis.seconds());
}
tty->print_cr (" iterGVN : %3.3f sec", Phase::_t_iterGVN.seconds()); tty->print_cr (" iterGVN : %3.3f sec", Phase::_t_iterGVN.seconds());
tty->print_cr (" idealLoop : %3.3f sec", Phase::_t_idealLoop.seconds()); tty->print_cr (" idealLoop : %3.3f sec", Phase::_t_idealLoop.seconds());
tty->print_cr (" idealLoopVerify: %3.3f sec", Phase::_t_idealLoopVerify.seconds()); tty->print_cr (" idealLoopVerify: %3.3f sec", Phase::_t_idealLoopVerify.seconds());
tty->print_cr (" ccp : %3.3f sec", Phase::_t_ccp.seconds()); tty->print_cr (" ccp : %3.3f sec", Phase::_t_ccp.seconds());
tty->print_cr (" iterGVN2 : %3.3f sec", Phase::_t_iterGVN2.seconds()); tty->print_cr (" iterGVN2 : %3.3f sec", Phase::_t_iterGVN2.seconds());
tty->print_cr (" macroExpand : %3.3f sec", Phase::_t_macroExpand.seconds());
tty->print_cr (" graphReshape : %3.3f sec", Phase::_t_graphReshaping.seconds()); tty->print_cr (" graphReshape : %3.3f sec", Phase::_t_graphReshaping.seconds());
double optimizer_subtotal = Phase::_t_iterGVN.seconds() + double optimizer_subtotal = Phase::_t_iterGVN.seconds() +
Phase::_t_idealLoop.seconds() + Phase::_t_ccp.seconds() + Phase::_t_idealLoop.seconds() + Phase::_t_ccp.seconds() +
...@@ -133,18 +135,15 @@ void Phase::print_timers() { ...@@ -133,18 +135,15 @@ void Phase::print_timers() {
double percent_of_regalloc = ((regalloc_subtotal == 0.0) ? 0.0 : (regalloc_subtotal / Phase::_t_registerAllocation.seconds() * 100.0)); double percent_of_regalloc = ((regalloc_subtotal == 0.0) ? 0.0 : (regalloc_subtotal / Phase::_t_registerAllocation.seconds() * 100.0));
tty->print_cr (" subtotal : %3.3f sec, %3.2f %%", regalloc_subtotal, percent_of_regalloc); tty->print_cr (" subtotal : %3.3f sec, %3.2f %%", regalloc_subtotal, percent_of_regalloc);
} }
tty->print_cr (" macroExpand : %3.3f sec", Phase::_t_macroExpand.seconds());
tty->print_cr (" blockOrdering : %3.3f sec", Phase::_t_blockOrdering.seconds()); tty->print_cr (" blockOrdering : %3.3f sec", Phase::_t_blockOrdering.seconds());
tty->print_cr (" peephole : %3.3f sec", Phase::_t_peephole.seconds()); tty->print_cr (" peephole : %3.3f sec", Phase::_t_peephole.seconds());
tty->print_cr (" codeGen : %3.3f sec", Phase::_t_codeGeneration.seconds()); tty->print_cr (" codeGen : %3.3f sec", Phase::_t_codeGeneration.seconds());
tty->print_cr (" install_code : %3.3f sec", Phase::_t_registerMethod.seconds()); tty->print_cr (" install_code : %3.3f sec", Phase::_t_registerMethod.seconds());
tty->print_cr (" -------------- : ----------"); tty->print_cr (" -------------- : ----------");
double phase_subtotal = Phase::_t_parser.seconds() + double phase_subtotal = Phase::_t_parser.seconds() +
(DoEscapeAnalysis ? Phase::_t_escapeAnalysis.seconds() : 0.0) +
Phase::_t_optimizer.seconds() + Phase::_t_graphReshaping.seconds() + Phase::_t_optimizer.seconds() + Phase::_t_graphReshaping.seconds() +
Phase::_t_matcher.seconds() + Phase::_t_scheduler.seconds() + Phase::_t_matcher.seconds() + Phase::_t_scheduler.seconds() +
Phase::_t_registerAllocation.seconds() + Phase::_t_blockOrdering.seconds() + Phase::_t_registerAllocation.seconds() + Phase::_t_blockOrdering.seconds() +
Phase::_t_macroExpand.seconds() + Phase::_t_peephole.seconds() +
Phase::_t_codeGeneration.seconds() + Phase::_t_registerMethod.seconds(); Phase::_t_codeGeneration.seconds() + Phase::_t_registerMethod.seconds();
double percent_of_method_compile = ((phase_subtotal == 0.0) ? 0.0 : phase_subtotal / Phase::_t_methodCompilation.seconds()) * 100.0; double percent_of_method_compile = ((phase_subtotal == 0.0) ? 0.0 : phase_subtotal / Phase::_t_methodCompilation.seconds()) * 100.0;
// counters inside Compile::CodeGen include time for adapters and stubs // counters inside Compile::CodeGen include time for adapters and stubs
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册