1.1 --- a/src/share/vm/opto/escape.hpp Fri Mar 09 13:34:45 2012 -0800 1.2 +++ b/src/share/vm/opto/escape.hpp Mon Mar 12 10:46:47 2012 -0700 1.3 @@ -1,5 +1,5 @@ 1.4 /* 1.5 - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. 1.6 + * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. 1.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.8 * 1.9 * This code is free software; you can redistribute it and/or modify it 1.10 @@ -115,18 +115,36 @@ 1.11 class CallNode; 1.12 class PhiNode; 1.13 class PhaseTransform; 1.14 +class PointsToNode; 1.15 class Type; 1.16 class TypePtr; 1.17 class VectorSet; 1.18 1.19 -class PointsToNode { 1.20 -friend class ConnectionGraph; 1.21 +class JavaObjectNode; 1.22 +class LocalVarNode; 1.23 +class FieldNode; 1.24 +class ArraycopyNode; 1.25 + 1.26 +// ConnectionGraph nodes 1.27 +class PointsToNode : public ResourceObj { 1.28 + GrowableArray<PointsToNode*> _edges; // List of nodes this node points to 1.29 + GrowableArray<PointsToNode*> _uses; // List of nodes which point to this node 1.30 + 1.31 + const u1 _type; // NodeType 1.32 + u1 _flags; // NodeFlags 1.33 + u1 _escape; // EscapeState of object 1.34 + u1 _fields_escape; // EscapeState of object's fields 1.35 + 1.36 + Node* const _node; // Ideal node corresponding to this PointsTo node. 1.37 + const int _idx; // Cached ideal node's _idx 1.38 + 1.39 public: 1.40 typedef enum { 1.41 UnknownType = 0, 1.42 JavaObject = 1, 1.43 LocalVar = 2, 1.44 - Field = 3 1.45 + Field = 3, 1.46 + Arraycopy = 4 1.47 } NodeType; 1.48 1.49 typedef enum { 1.50 @@ -140,178 +158,387 @@ 1.51 } EscapeState; 1.52 1.53 typedef enum { 1.54 - UnknownEdge = 0, 1.55 - PointsToEdge = 1, 1.56 - DeferredEdge = 2, 1.57 - FieldEdge = 3 1.58 - } EdgeType; 1.59 + ScalarReplaceable = 1, // Not escaped object could be replaced with scalar 1.60 + PointsToUnknown = 2, // Has edge to phantom_object 1.61 + ArraycopySrc = 4, // Has edge from Arraycopy node 1.62 + ArraycopyDst = 8 // Has edge to Arraycopy node 1.63 + } NodeFlags; 1.64 1.65 -private: 1.66 - enum { 1.67 - EdgeMask = 3, 1.68 - EdgeShift = 2, 1.69 1.70 - INITIAL_EDGE_COUNT = 4 1.71 - }; 1.72 - 1.73 - NodeType _type; 1.74 - EscapeState _escape; 1.75 - GrowableArray<uint>* _edges; // outgoing edges 1.76 - Node* _node; // Ideal node corresponding to this PointsTo node. 1.77 - int _offset; // Object fields offsets. 1.78 - bool _scalar_replaceable; // Not escaped object could be replaced with scalar 1.79 - bool _has_unknown_ptr; // Has edge to phantom_object 1.80 - 1.81 -public: 1.82 - PointsToNode(): 1.83 - _type(UnknownType), 1.84 - _escape(UnknownEscape), 1.85 - _edges(NULL), 1.86 - _node(NULL), 1.87 - _offset(-1), 1.88 - _has_unknown_ptr(false), 1.89 - _scalar_replaceable(true) {} 1.90 - 1.91 - 1.92 - EscapeState escape_state() const { return _escape; } 1.93 - NodeType node_type() const { return _type;} 1.94 - int offset() { return _offset;} 1.95 - bool scalar_replaceable() { return _scalar_replaceable;} 1.96 - bool has_unknown_ptr() { return _has_unknown_ptr;} 1.97 - 1.98 - void set_offset(int offs) { _offset = offs;} 1.99 - void set_escape_state(EscapeState state) { _escape = state; } 1.100 - void set_node_type(NodeType ntype) { 1.101 - assert(_type == UnknownType || _type == ntype, "Can't change node type"); 1.102 - _type = ntype; 1.103 - } 1.104 - void set_scalar_replaceable(bool v) { _scalar_replaceable = v; } 1.105 - void set_has_unknown_ptr() { _has_unknown_ptr = true; } 1.106 - 1.107 - // count of outgoing edges 1.108 - uint edge_count() const { return (_edges == NULL) ? 0 : _edges->length(); } 1.109 - 1.110 - // node index of target of outgoing edge "e" 1.111 - uint edge_target(uint e) const { 1.112 - assert(_edges != NULL, "valid edge index"); 1.113 - return (_edges->at(e) >> EdgeShift); 1.114 - } 1.115 - // type of outgoing edge "e" 1.116 - EdgeType edge_type(uint e) const { 1.117 - assert(_edges != NULL, "valid edge index"); 1.118 - return (EdgeType) (_edges->at(e) & EdgeMask); 1.119 + PointsToNode(Compile *C, Node* n, EscapeState es, NodeType type): 1.120 + _edges(C->comp_arena(), 2, 0, NULL), 1.121 + _uses (C->comp_arena(), 2, 0, NULL), 1.122 + _node(n), 1.123 + _idx(n->_idx), 1.124 + _type((u1)type), 1.125 + _escape((u1)es), 1.126 + _fields_escape((u1)es), 1.127 + _flags(ScalarReplaceable) { 1.128 + assert(n != NULL && es != UnknownEscape, "sanity"); 1.129 } 1.130 1.131 - // add a edge of the specified type pointing to the specified target 1.132 - void add_edge(uint targIdx, EdgeType et); 1.133 + Node* ideal_node() const { return _node; } 1.134 + int idx() const { return _idx; } 1.135 1.136 - // remove an edge of the specified type pointing to the specified target 1.137 - void remove_edge(uint targIdx, EdgeType et); 1.138 + bool is_JavaObject() const { return _type == (u1)JavaObject; } 1.139 + bool is_LocalVar() const { return _type == (u1)LocalVar; } 1.140 + bool is_Field() const { return _type == (u1)Field; } 1.141 + bool is_Arraycopy() const { return _type == (u1)Arraycopy; } 1.142 + 1.143 + JavaObjectNode* as_JavaObject() { assert(is_JavaObject(),""); return (JavaObjectNode*)this; } 1.144 + LocalVarNode* as_LocalVar() { assert(is_LocalVar(),""); return (LocalVarNode*)this; } 1.145 + FieldNode* as_Field() { assert(is_Field(),""); return (FieldNode*)this; } 1.146 + ArraycopyNode* as_Arraycopy() { assert(is_Arraycopy(),""); return (ArraycopyNode*)this; } 1.147 + 1.148 + EscapeState escape_state() const { return (EscapeState)_escape; } 1.149 + void set_escape_state(EscapeState state) { _escape = (u1)state; } 1.150 + 1.151 + EscapeState fields_escape_state() const { return (EscapeState)_fields_escape; } 1.152 + void set_fields_escape_state(EscapeState state) { _fields_escape = (u1)state; } 1.153 + 1.154 + bool has_unknown_ptr() const { return (_flags & PointsToUnknown) != 0; } 1.155 + void set_has_unknown_ptr() { _flags |= PointsToUnknown; } 1.156 + 1.157 + bool arraycopy_src() const { return (_flags & ArraycopySrc) != 0; } 1.158 + void set_arraycopy_src() { _flags |= ArraycopySrc; } 1.159 + bool arraycopy_dst() const { return (_flags & ArraycopyDst) != 0; } 1.160 + void set_arraycopy_dst() { _flags |= ArraycopyDst; } 1.161 + 1.162 + bool scalar_replaceable() const { return (_flags & ScalarReplaceable) != 0;} 1.163 + void set_scalar_replaceable(bool v) { 1.164 + if (v) 1.165 + _flags |= ScalarReplaceable; 1.166 + else 1.167 + _flags &= ~ScalarReplaceable; 1.168 + } 1.169 + 1.170 + int edge_count() const { return _edges.length(); } 1.171 + PointsToNode* edge(int e) const { return _edges.at(e); } 1.172 + bool add_edge(PointsToNode* edge) { return _edges.append_if_missing(edge); } 1.173 + 1.174 + int use_count() const { return _uses.length(); } 1.175 + PointsToNode* use(int e) const { return _uses.at(e); } 1.176 + bool add_use(PointsToNode* use) { return _uses.append_if_missing(use); } 1.177 + 1.178 + // Mark base edge use to distinguish from stored value edge. 1.179 + bool add_base_use(FieldNode* use) { return _uses.append_if_missing((PointsToNode*)((intptr_t)use + 1)); } 1.180 + static bool is_base_use(PointsToNode* use) { return (((intptr_t)use) & 1); } 1.181 + static PointsToNode* get_use_node(PointsToNode* use) { return (PointsToNode*)(((intptr_t)use) & ~1); } 1.182 + 1.183 + // Return true if this node points to specified node or nodes it points to. 1.184 + bool points_to(JavaObjectNode* ptn) const; 1.185 + 1.186 + // Return true if this node points only to non-escaping allocations. 1.187 + bool non_escaping_allocation(); 1.188 + 1.189 + // Return true if one node points to an other. 1.190 + bool meet(PointsToNode* ptn); 1.191 1.192 #ifndef PRODUCT 1.193 + NodeType node_type() const { return (NodeType)_type;} 1.194 void dump(bool print_state=true) const; 1.195 #endif 1.196 1.197 }; 1.198 1.199 +class LocalVarNode: public PointsToNode { 1.200 +public: 1.201 + LocalVarNode(Compile *C, Node* n, EscapeState es): 1.202 + PointsToNode(C, n, es, LocalVar) {} 1.203 +}; 1.204 + 1.205 +class JavaObjectNode: public PointsToNode { 1.206 +public: 1.207 + JavaObjectNode(Compile *C, Node* n, EscapeState es): 1.208 + PointsToNode(C, n, es, JavaObject) { 1.209 + if (es > NoEscape) 1.210 + set_scalar_replaceable(false); 1.211 + } 1.212 +}; 1.213 + 1.214 +class FieldNode: public PointsToNode { 1.215 + GrowableArray<PointsToNode*> _bases; // List of JavaObject nodes which point to this node 1.216 + const int _offset; // Field's offset. 1.217 + const bool _is_oop; // Field points to object 1.218 + bool _has_unknown_base; // Has phantom_object base 1.219 +public: 1.220 + FieldNode(Compile *C, Node* n, EscapeState es, int offs, bool is_oop): 1.221 + PointsToNode(C, n, es, Field), 1.222 + _offset(offs), _is_oop(is_oop), 1.223 + _has_unknown_base(false) {} 1.224 + 1.225 + int offset() const { return _offset;} 1.226 + bool is_oop() const { return _is_oop;} 1.227 + bool has_unknown_base() const { return _has_unknown_base; } 1.228 + void set_has_unknown_base() { _has_unknown_base = true; } 1.229 + 1.230 + int base_count() const { return _bases.length(); } 1.231 + PointsToNode* base(int e) const { return _bases.at(e); } 1.232 + bool add_base(PointsToNode* base) { return _bases.append_if_missing(base); } 1.233 +#ifdef ASSERT 1.234 + // Return true if bases points to this java object. 1.235 + bool has_base(JavaObjectNode* ptn) const; 1.236 +#endif 1.237 + 1.238 +}; 1.239 + 1.240 +class ArraycopyNode: public PointsToNode { 1.241 +public: 1.242 + ArraycopyNode(Compile *C, Node* n, EscapeState es): 1.243 + PointsToNode(C, n, es, Arraycopy) {} 1.244 +}; 1.245 + 1.246 +// Iterators for PointsTo node's edges: 1.247 +// for (EdgeIterator i(n); i.has_next(); i.next()) { 1.248 +// PointsToNode* u = i.get(); 1.249 +class PointsToIterator: public StackObj { 1.250 +protected: 1.251 + const PointsToNode* node; 1.252 + const int cnt; 1.253 + int i; 1.254 +public: 1.255 + inline PointsToIterator(const PointsToNode* n, int cnt) : node(n), cnt(cnt), i(0) { } 1.256 + inline bool has_next() const { return i < cnt; } 1.257 + inline void next() { i++; } 1.258 + PointsToNode* get() const { ShouldNotCallThis(); return NULL; } 1.259 +}; 1.260 + 1.261 +class EdgeIterator: public PointsToIterator { 1.262 +public: 1.263 + inline EdgeIterator(const PointsToNode* n) : PointsToIterator(n, n->edge_count()) { } 1.264 + inline PointsToNode* get() const { return node->edge(i); } 1.265 +}; 1.266 + 1.267 +class UseIterator: public PointsToIterator { 1.268 +public: 1.269 + inline UseIterator(const PointsToNode* n) : PointsToIterator(n, n->use_count()) { } 1.270 + inline PointsToNode* get() const { return node->use(i); } 1.271 +}; 1.272 + 1.273 +class BaseIterator: public PointsToIterator { 1.274 +public: 1.275 + inline BaseIterator(const FieldNode* n) : PointsToIterator(n, n->base_count()) { } 1.276 + inline PointsToNode* get() const { return ((PointsToNode*)node)->as_Field()->base(i); } 1.277 +}; 1.278 + 1.279 + 1.280 class ConnectionGraph: public ResourceObj { 1.281 private: 1.282 - GrowableArray<PointsToNode> _nodes; // Connection graph nodes indexed 1.283 - // by ideal node index. 1.284 + GrowableArray<PointsToNode*> _nodes; // Map from ideal nodes to 1.285 + // ConnectionGraph nodes. 1.286 1.287 - Unique_Node_List _delayed_worklist; // Nodes to be processed before 1.288 - // the call build_connection_graph(). 1.289 + GrowableArray<PointsToNode*> _worklist; // Nodes to be processed 1.290 1.291 - GrowableArray<MergeMemNode *> _mergemem_worklist; // List of all MergeMem nodes 1.292 + bool _collecting; // Indicates whether escape information 1.293 + // is still being collected. If false, 1.294 + // no new nodes will be processed. 1.295 1.296 - VectorSet _processed; // Records which nodes have been 1.297 - // processed. 1.298 + bool _verify; // verify graph 1.299 1.300 - bool _collecting; // Indicates whether escape information 1.301 - // is still being collected. If false, 1.302 - // no new nodes will be processed. 1.303 + JavaObjectNode* phantom_obj; // Unknown object 1.304 + JavaObjectNode* null_obj; 1.305 + Node* _pcmp_neq; // ConI(#CC_GT) 1.306 + Node* _pcmp_eq; // ConI(#CC_EQ) 1.307 1.308 - bool _progress; // Indicates whether new Graph's edges 1.309 - // were created. 1.310 + Compile* _compile; // Compile object for current compilation 1.311 + PhaseIterGVN* _igvn; // Value numbering 1.312 1.313 - uint _phantom_object; // Index of globally escaping object 1.314 - // that pointer values loaded from 1.315 - // a field which has not been set 1.316 - // are assumed to point to. 1.317 - uint _oop_null; // ConP(#NULL)->_idx 1.318 - uint _noop_null; // ConN(#NULL)->_idx 1.319 - Node* _pcmp_neq; // ConI(#CC_GT) 1.320 - Node* _pcmp_eq; // ConI(#CC_EQ) 1.321 - 1.322 - Compile * _compile; // Compile object for current compilation 1.323 - PhaseIterGVN * _igvn; // Value numbering 1.324 + Unique_Node_List ideal_nodes; // Used by CG construction and types splitting. 1.325 1.326 // Address of an element in _nodes. Used when the element is to be modified 1.327 - PointsToNode *ptnode_adr(uint idx) const { 1.328 + PointsToNode* ptnode_adr(int idx) const { 1.329 // There should be no new ideal nodes during ConnectionGraph build, 1.330 - // growableArray::adr_at() will throw assert otherwise. 1.331 - return _nodes.adr_at(idx); 1.332 + // growableArray::at() will throw assert otherwise. 1.333 + return _nodes.at(idx); 1.334 } 1.335 uint nodes_size() const { return _nodes.length(); } 1.336 1.337 - bool is_null_ptr(uint idx) const { return (idx == _noop_null || idx == _oop_null); } 1.338 + // Add nodes to ConnectionGraph. 1.339 + void add_local_var(Node* n, PointsToNode::EscapeState es); 1.340 + void add_java_object(Node* n, PointsToNode::EscapeState es); 1.341 + void add_field(Node* n, PointsToNode::EscapeState es, int offset); 1.342 + void add_arraycopy(Node* n, PointsToNode::EscapeState es, PointsToNode* src, PointsToNode* dst); 1.343 1.344 - // Add node to ConnectionGraph. 1.345 - void add_node(Node *n, PointsToNode::NodeType nt, PointsToNode::EscapeState es, bool done); 1.346 + // Compute the escape state for arguments to a call. 1.347 + void process_call_arguments(CallNode *call); 1.348 + 1.349 + // Add PointsToNode node corresponding to a call 1.350 + void add_call_node(CallNode* call); 1.351 + 1.352 + // Map ideal node to existing PointsTo node (usually phantom_object). 1.353 + void map_ideal_node(Node *n, PointsToNode* ptn) { 1.354 + assert(ptn != NULL, "only existing PointsTo node"); 1.355 + _nodes.at_put(n->_idx, ptn); 1.356 + } 1.357 + 1.358 + // Create PointsToNode node and add it to Connection Graph. 1.359 + void add_node_to_connection_graph(Node *n, Unique_Node_List *delayed_worklist); 1.360 + 1.361 + // Add final simple edges to graph. 1.362 + void add_final_edges(Node *n); 1.363 + 1.364 + // Finish Graph construction. 1.365 + bool complete_connection_graph(GrowableArray<PointsToNode*>& ptnodes_worklist, 1.366 + GrowableArray<JavaObjectNode*>& non_escaped_worklist, 1.367 + GrowableArray<JavaObjectNode*>& java_objects_worklist, 1.368 + GrowableArray<FieldNode*>& oop_fields_worklist); 1.369 + 1.370 +#ifdef ASSERT 1.371 + void verify_connection_graph(GrowableArray<PointsToNode*>& ptnodes_worklist, 1.372 + GrowableArray<JavaObjectNode*>& non_escaped_worklist, 1.373 + GrowableArray<JavaObjectNode*>& java_objects_worklist, 1.374 + GrowableArray<Node*>& addp_worklist); 1.375 +#endif 1.376 + 1.377 + // Add all references to this JavaObject node. 1.378 + int add_java_object_edges(JavaObjectNode* jobj, bool populate_worklist); 1.379 + 1.380 + // Put node on worklist if it is (or was) not there. 1.381 + void add_to_worklist(PointsToNode* pt) { 1.382 + _worklist.push(pt); 1.383 + return; 1.384 + } 1.385 + 1.386 + // Put on worklist all uses of this node. 1.387 + void add_uses_to_worklist(PointsToNode* pt) { 1.388 + for (UseIterator i(pt); i.has_next(); i.next()) 1.389 + _worklist.push(i.get()); 1.390 + } 1.391 + 1.392 + // Put on worklist all field's uses and related field nodes. 1.393 + void add_field_uses_to_worklist(FieldNode* field); 1.394 + 1.395 + // Put on worklist all related field nodes. 1.396 + void add_fields_to_worklist(FieldNode* field, PointsToNode* base); 1.397 + 1.398 + // Find fields which have unknown value. 1.399 + int find_field_value(FieldNode* field); 1.400 + 1.401 + // Find fields initializing values for allocations. 1.402 + int find_init_values(JavaObjectNode* ptn, PointsToNode* init_val, PhaseTransform* phase); 1.403 + 1.404 + // Set the escape state of an object and its fields. 1.405 + void set_escape_state(PointsToNode* ptn, PointsToNode::EscapeState esc) { 1.406 + // Don't change non-escaping state of NULL pointer. 1.407 + if (ptn != null_obj) { 1.408 + if (ptn->escape_state() < esc) 1.409 + ptn->set_escape_state(esc); 1.410 + if (ptn->fields_escape_state() < esc) 1.411 + ptn->set_fields_escape_state(esc); 1.412 + } 1.413 + } 1.414 + void set_fields_escape_state(PointsToNode* ptn, PointsToNode::EscapeState esc) { 1.415 + // Don't change non-escaping state of NULL pointer. 1.416 + if (ptn != null_obj) { 1.417 + if (ptn->fields_escape_state() < esc) 1.418 + ptn->set_fields_escape_state(esc); 1.419 + } 1.420 + } 1.421 + 1.422 + // Propagate GlobalEscape and ArgEscape escape states to all nodes 1.423 + // and check that we still have non-escaping java objects. 1.424 + bool find_non_escaped_objects(GrowableArray<PointsToNode*>& ptnodes_worklist, 1.425 + GrowableArray<JavaObjectNode*>& non_escaped_worklist); 1.426 + 1.427 + // Adjust scalar_replaceable state after Connection Graph is built. 1.428 + void adjust_scalar_replaceable_state(JavaObjectNode* jobj); 1.429 + 1.430 + // Optimize ideal graph. 1.431 + void optimize_ideal_graph(GrowableArray<Node*>& ptr_cmp_worklist, 1.432 + GrowableArray<Node*>& storestore_worklist); 1.433 + // Optimize objects compare. 1.434 + Node* optimize_ptr_compare(Node* n); 1.435 + 1.436 + // Returns unique corresponding java object or NULL. 1.437 + JavaObjectNode* unique_java_object(Node *n); 1.438 + 1.439 + // Add an edge of the specified type pointing to the specified target. 1.440 + bool add_edge(PointsToNode* from, PointsToNode* to) { 1.441 + assert(!from->is_Field() || from->as_Field()->is_oop(), "sanity"); 1.442 + 1.443 + if (to == phantom_obj) { 1.444 + if (from->has_unknown_ptr()) { 1.445 + return false; // already points to phantom_obj 1.446 + } 1.447 + from->set_has_unknown_ptr(); 1.448 + } 1.449 + 1.450 + bool is_new = from->add_edge(to); 1.451 + assert(to != phantom_obj || is_new, "sanity"); 1.452 + if (is_new) { // New edge? 1.453 + assert(!_verify, "graph is incomplete"); 1.454 + is_new = to->add_use(from); 1.455 + assert(is_new, "use should be also new"); 1.456 + } 1.457 + return is_new; 1.458 + } 1.459 + 1.460 + // Add an edge from Field node to its base and back. 1.461 + bool add_base(FieldNode* from, PointsToNode* to) { 1.462 + assert(!to->is_Arraycopy(), "sanity"); 1.463 + if (to == phantom_obj) { 1.464 + if (from->has_unknown_base()) { 1.465 + return false; // already has phantom_obj base 1.466 + } 1.467 + from->set_has_unknown_base(); 1.468 + } 1.469 + bool is_new = from->add_base(to); 1.470 + assert(to != phantom_obj || is_new, "sanity"); 1.471 + if (is_new) { // New edge? 1.472 + assert(!_verify, "graph is incomplete"); 1.473 + if (to == null_obj) 1.474 + return is_new; // Don't add fields to NULL pointer. 1.475 + if (to->is_JavaObject()) { 1.476 + is_new = to->add_edge(from); 1.477 + } else { 1.478 + is_new = to->add_base_use(from); 1.479 + } 1.480 + assert(is_new, "use should be also new"); 1.481 + } 1.482 + return is_new; 1.483 + } 1.484 + 1.485 + // Add LocalVar node and edge if possible 1.486 + void add_local_var_and_edge(Node* n, PointsToNode::EscapeState es, Node* to, 1.487 + Unique_Node_List *delayed_worklist) { 1.488 + PointsToNode* ptn = ptnode_adr(to->_idx); 1.489 + if (delayed_worklist != NULL) { // First iteration of CG construction 1.490 + add_local_var(n, es); 1.491 + if (ptn == NULL) { 1.492 + delayed_worklist->push(n); 1.493 + return; // Process it later. 1.494 + } 1.495 + } else { 1.496 + assert(ptn != NULL, "node should be registered"); 1.497 + } 1.498 + add_edge(ptnode_adr(n->_idx), ptn); 1.499 + } 1.500 + 1.501 + // Helper functions 1.502 + bool is_oop_field(Node* n, int offset); 1.503 + static Node* get_addp_base(Node *addp); 1.504 + static Node* find_second_addp(Node* addp, Node* n); 1.505 1.506 // offset of a field reference 1.507 int address_offset(Node* adr, PhaseTransform *phase); 1.508 1.509 - // compute the escape state for arguments to a call 1.510 - void process_call_arguments(CallNode *call, PhaseTransform *phase); 1.511 1.512 - // compute the escape state for the return value of a call 1.513 - void process_call_result(ProjNode *resproj, PhaseTransform *phase); 1.514 + // Propagate unique types created for unescaped allocated objects 1.515 + // through the graph 1.516 + void split_unique_types(GrowableArray<Node *> &alloc_worklist); 1.517 1.518 - // Populate Connection Graph with Ideal nodes. 1.519 - void record_for_escape_analysis(Node *n, PhaseTransform *phase); 1.520 + // Helper methods for unique types split. 1.521 + bool split_AddP(Node *addp, Node *base); 1.522 1.523 - // Build Connection Graph and set nodes escape state. 1.524 - void build_connection_graph(Node *n, PhaseTransform *phase); 1.525 + PhiNode *create_split_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *> &orig_phi_worklist, bool &new_created); 1.526 + PhiNode *split_memory_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *> &orig_phi_worklist); 1.527 1.528 - // walk the connection graph starting at the node corresponding to "n" and 1.529 - // add the index of everything it could point to, to "ptset". This may cause 1.530 - // Phi's encountered to get (re)processed (which requires "phase".) 1.531 - VectorSet* PointsTo(Node * n); 1.532 + void move_inst_mem(Node* n, GrowableArray<PhiNode *> &orig_phis); 1.533 + Node* find_inst_mem(Node* mem, int alias_idx,GrowableArray<PhiNode *> &orig_phi_worklist); 1.534 + Node* step_through_mergemem(MergeMemNode *mmem, int alias_idx, const TypeOopPtr *toop); 1.535 1.536 - // Reused structures for PointsTo(). 1.537 - VectorSet pt_ptset; 1.538 - VectorSet pt_visited; 1.539 - GrowableArray<uint> pt_worklist; 1.540 1.541 - // Edge manipulation. The "from_i" and "to_i" arguments are the 1.542 - // node indices of the source and destination of the edge 1.543 - void add_pointsto_edge(uint from_i, uint to_i); 1.544 - void add_deferred_edge(uint from_i, uint to_i); 1.545 - void add_field_edge(uint from_i, uint to_i, int offs); 1.546 - 1.547 - // Add an edge of the specified type pointing to the specified target. 1.548 - // Set _progress if new edge is added. 1.549 - void add_edge(PointsToNode *f, uint to_i, PointsToNode::EdgeType et) { 1.550 - uint e_cnt = f->edge_count(); 1.551 - f->add_edge(to_i, et); 1.552 - _progress |= (f->edge_count() != e_cnt); 1.553 - } 1.554 - 1.555 - // Add an edge to node given by "to_i" from any field of adr_i whose offset 1.556 - // matches "offset" A deferred edge is added if to_i is a LocalVar, and 1.557 - // a pointsto edge is added if it is a JavaObject 1.558 - void add_edge_from_fields(uint adr, uint to_i, int offs); 1.559 - 1.560 - // Add a deferred edge from node given by "from_i" to any field 1.561 - // of adr_i whose offset matches "offset" 1.562 - void add_deferred_edge_to_fields(uint from_i, uint adr, int offs); 1.563 - 1.564 - 1.565 - // Remove outgoing deferred edges from the node referenced by "ni". 1.566 - // Any outgoing edges from the target of the deferred edge are copied 1.567 - // to "ni". 1.568 - void remove_deferred(uint ni, GrowableArray<uint>* deferred_edges, VectorSet* visited); 1.569 + GrowableArray<MergeMemNode*> _mergemem_worklist; // List of all MergeMem nodes 1.570 1.571 Node_Array _node_map; // used for bookeeping during type splitting 1.572 // Used for the following purposes: 1.573 @@ -320,21 +547,18 @@ 1.574 // MemNode - new memory input for this node 1.575 // ChecCastPP - allocation that this is a cast of 1.576 // allocation - CheckCastPP of the allocation 1.577 - bool split_AddP(Node *addp, Node *base, PhaseGVN *igvn); 1.578 - PhiNode *create_split_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *> &orig_phi_worklist, PhaseGVN *igvn, bool &new_created); 1.579 - PhiNode *split_memory_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *> &orig_phi_worklist, PhaseGVN *igvn); 1.580 - void move_inst_mem(Node* n, GrowableArray<PhiNode *> &orig_phis, PhaseGVN *igvn); 1.581 - Node *find_inst_mem(Node *mem, int alias_idx,GrowableArray<PhiNode *> &orig_phi_worklist, PhaseGVN *igvn); 1.582 - 1.583 - // Propagate unique types created for unescaped allocated objects 1.584 - // through the graph 1.585 - void split_unique_types(GrowableArray<Node *> &alloc_worklist); 1.586 1.587 // manage entries in _node_map 1.588 - void set_map(int idx, Node *n) { _node_map.map(idx, n); } 1.589 - Node *get_map(int idx) { return _node_map[idx]; } 1.590 - PhiNode *get_map_phi(int idx) { 1.591 - Node *phi = _node_map[idx]; 1.592 + 1.593 + void set_map(Node* from, Node* to) { 1.594 + ideal_nodes.push(from); 1.595 + _node_map.map(from->_idx, to); 1.596 + } 1.597 + 1.598 + Node* get_map(int idx) { return _node_map[idx]; } 1.599 + 1.600 + PhiNode* get_map_phi(int idx) { 1.601 + Node* phi = _node_map[idx]; 1.602 return (phi == NULL) ? NULL : phi->as_Phi(); 1.603 } 1.604 1.605 @@ -344,23 +568,6 @@ 1.606 _igvn->add_users_to_worklist(n); 1.607 } 1.608 1.609 - // Set the escape state of a node 1.610 - void set_escape_state(uint ni, PointsToNode::EscapeState es); 1.611 - 1.612 - // Find fields initializing values for allocations. 1.613 - void find_init_values(Node* n, VectorSet* visited, PhaseTransform* phase); 1.614 - 1.615 - // Adjust escape state after Connection Graph is built. 1.616 - void adjust_escape_state(Node* n); 1.617 - 1.618 - // Propagate escape states to referenced nodes. 1.619 - bool propagate_escape_state(GrowableArray<int>* cg_worklist, 1.620 - GrowableArray<uint>* worklist, 1.621 - PointsToNode::EscapeState esc_state); 1.622 - 1.623 - // Optimize objects compare. 1.624 - Node* optimize_ptr_compare(Node* n); 1.625 - 1.626 // Compute the escape information 1.627 bool compute_escape(); 1.628 1.629 @@ -373,11 +580,10 @@ 1.630 // Perform escape analysis 1.631 static void do_analysis(Compile *C, PhaseIterGVN *igvn); 1.632 1.633 - // escape state of a node 1.634 - PointsToNode::EscapeState escape_state(Node *n); 1.635 + bool not_global_escape(Node *n); 1.636 1.637 #ifndef PRODUCT 1.638 - void dump(); 1.639 + void dump(GrowableArray<PointsToNode*>& ptnodes_worklist); 1.640 #endif 1.641 }; 1.642