src/share/vm/opto/escape.hpp

changeset 500
99269dbf4ba8
parent 435
a61af66fc99e
child 536
a6cb86dd209b
equal deleted inserted replaced
499:b8f5ba577b02 500:99269dbf4ba8
23 */ 23 */
24 24
25 // 25 //
26 // Adaptation for C2 of the escape analysis algorithm described in: 26 // Adaptation for C2 of the escape analysis algorithm described in:
27 // 27 //
28 // [Choi99] Jong-Deok Shoi, Manish Gupta, Mauricio Seffano, Vugranam C. Sreedhar, 28 // [Choi99] Jong-Deok Shoi, Manish Gupta, Mauricio Seffano,
29 // Sam Midkiff, "Escape Analysis for Java", Procedings of ACM SIGPLAN 29 // Vugranam C. Sreedhar, Sam Midkiff,
30 // OOPSLA Conference, November 1, 1999 30 // "Escape Analysis for Java", Procedings of ACM SIGPLAN
31 // OOPSLA Conference, November 1, 1999
31 // 32 //
32 // The flow-insensitive analysis described in the paper has been implemented. 33 // The flow-insensitive analysis described in the paper has been implemented.
33 // 34 //
34 // The analysis requires construction of a "connection graph" (CG) for the method being 35 // The analysis requires construction of a "connection graph" (CG) for
35 // analyzed. The nodes of the connection graph are: 36 // the method being analyzed. The nodes of the connection graph are:
36 // 37 //
37 // - Java objects (JO) 38 // - Java objects (JO)
38 // - Local variables (LV) 39 // - Local variables (LV)
39 // - Fields of an object (OF), these also include array elements 40 // - Fields of an object (OF), these also include array elements
40 // 41 //
41 // The CG contains 3 types of edges: 42 // The CG contains 3 types of edges:
42 // 43 //
43 // - PointsTo (-P>) {LV,OF} to JO 44 // - PointsTo (-P>) {LV, OF} to JO
44 // - Deferred (-D>) from {LV, OF} to {LV, OF} 45 // - Deferred (-D>) from {LV, OF} to {LV, OF}
45 // - Field (-F>) from JO to OF 46 // - Field (-F>) from JO to OF
46 // 47 //
47 // The following utility functions is used by the algorithm: 48 // The following utility functions is used by the algorithm:
48 // 49 //
49 // PointsTo(n) - n is any CG node, it returns the set of JO that n could 50 // PointsTo(n) - n is any CG node, it returns the set of JO that n could
50 // point to. 51 // point to.
51 // 52 //
52 // The algorithm describes how to construct the connection graph in the following 4 cases: 53 // The algorithm describes how to construct the connection graph
54 // in the following 4 cases:
53 // 55 //
54 // Case Edges Created 56 // Case Edges Created
55 // 57 //
56 // (1) p = new T() LV -P> JO 58 // (1) p = new T() LV -P> JO
57 // (2) p = q LV -D> LV 59 // (2) p = q LV -D> LV
58 // (3) p.f = q JO -F> OF, OF -D> LV 60 // (3) p.f = q JO -F> OF, OF -D> LV
59 // (4) p = q.f JO -F> OF, LV -D> OF 61 // (4) p = q.f JO -F> OF, LV -D> OF
60 // 62 //
61 // In all these cases, p and q are local variables. For static field references, we can 63 // In all these cases, p and q are local variables. For static field
62 // construct a local variable containing a reference to the static memory. 64 // references, we can construct a local variable containing a reference
65 // to the static memory.
63 // 66 //
64 // C2 does not have local variables. However for the purposes of constructing 67 // C2 does not have local variables. However for the purposes of constructing
65 // the connection graph, the following IR nodes are treated as local variables: 68 // the connection graph, the following IR nodes are treated as local variables:
66 // Phi (pointer values) 69 // Phi (pointer values)
67 // LoadP 70 // LoadP
68 // Proj (value returned from callnodes including allocations) 71 // Proj#5 (value returned from callnodes including allocations)
69 // CheckCastPP 72 // CheckCastPP, CastPP
70 // 73 //
71 // The LoadP, Proj and CheckCastPP behave like variables assigned to only once. Only 74 // The LoadP, Proj and CheckCastPP behave like variables assigned to only once.
72 // a Phi can have multiple assignments. Each input to a Phi is treated 75 // Only a Phi can have multiple assignments. Each input to a Phi is treated
73 // as an assignment to it. 76 // as an assignment to it.
74 // 77 //
75 // The following note types are JavaObject: 78 // The following node types are JavaObject:
76 // 79 //
77 // top() 80 // top()
78 // Allocate 81 // Allocate
79 // AllocateArray 82 // AllocateArray
80 // Parm (for incoming arguments) 83 // Parm (for incoming arguments)
84 // CastX2P ("unsafe" operations)
81 // CreateEx 85 // CreateEx
82 // ConP 86 // ConP
83 // LoadKlass 87 // LoadKlass
88 // ThreadLocal
84 // 89 //
85 // AddP nodes are fields. 90 // AddP nodes are fields.
86 // 91 //
87 // After building the graph, a pass is made over the nodes, deleting deferred 92 // After building the graph, a pass is made over the nodes, deleting deferred
88 // nodes and copying the edges from the target of the deferred edge to the 93 // nodes and copying the edges from the target of the deferred edge to the
89 // source. This results in a graph with no deferred edges, only: 94 // source. This results in a graph with no deferred edges, only:
90 // 95 //
91 // LV -P> JO 96 // LV -P> JO
92 // OF -P> JO 97 // OF -P> JO (the object whose oop is stored in the field)
93 // JO -F> OF 98 // JO -F> OF
94 // 99 //
95 // Then, for each node which is GlobalEscape, anything it could point to 100 // Then, for each node which is GlobalEscape, anything it could point to
96 // is marked GlobalEscape. Finally, for any node marked ArgEscape, anything 101 // is marked GlobalEscape. Finally, for any node marked ArgEscape, anything
97 // it could point to is marked ArgEscape. 102 // it could point to is marked ArgEscape.
108 113
109 class PointsToNode { 114 class PointsToNode {
110 friend class ConnectionGraph; 115 friend class ConnectionGraph;
111 public: 116 public:
112 typedef enum { 117 typedef enum {
113 UnknownType = 0, 118 UnknownType = 0,
114 JavaObject = 1, 119 JavaObject = 1,
115 LocalVar = 2, 120 LocalVar = 2,
116 Field = 3 121 Field = 3
117 } NodeType; 122 } NodeType;
118 123
119 typedef enum { 124 typedef enum {
120 UnknownEscape = 0, 125 UnknownEscape = 0,
121 NoEscape = 1, 126 NoEscape = 1, // A scalar replaceable object with unique type.
122 ArgEscape = 2, 127 ArgEscape = 2, // An object passed as argument or referenced by
123 GlobalEscape = 3 128 // argument (and not globally escape during call).
129 GlobalEscape = 3 // An object escapes the method and thread.
124 } EscapeState; 130 } EscapeState;
125 131
126 typedef enum { 132 typedef enum {
127 UnknownEdge = 0, 133 UnknownEdge = 0,
128 PointsToEdge = 1, 134 PointsToEdge = 1,
138 INITIAL_EDGE_COUNT = 4 144 INITIAL_EDGE_COUNT = 4
139 }; 145 };
140 146
141 NodeType _type; 147 NodeType _type;
142 EscapeState _escape; 148 EscapeState _escape;
143 GrowableArray<uint>* _edges; // outgoing edges 149 GrowableArray<uint>* _edges; // outgoing edges
144 int _offset; // for fields 150
145
146 bool _unique_type; // For allocated objects, this node may be a unique type
147 public: 151 public:
148 Node* _node; // Ideal node corresponding to this PointsTo node 152 Node* _node; // Ideal node corresponding to this PointsTo node.
149 int _inputs_processed; // the number of Phi inputs that have been processed so far 153 int _offset; // Object fields offsets.
150 bool _hidden_alias; // this node is an argument to a function which may return it 154 bool _scalar_replaceable;// Not escaped object could be replaced with scalar
151 // creating a hidden alias 155 bool _hidden_alias; // This node is an argument to a function.
152 156 // which may return it creating a hidden alias.
153 157
154 PointsToNode(): _offset(-1), _type(UnknownType), _escape(UnknownEscape), _edges(NULL), _node(NULL), _inputs_processed(0), _hidden_alias(false), _unique_type(true) {} 158 PointsToNode():
159 _type(UnknownType),
160 _escape(UnknownEscape),
161 _edges(NULL),
162 _node(NULL),
163 _offset(-1),
164 _scalar_replaceable(true),
165 _hidden_alias(false) {}
166
155 167
156 EscapeState escape_state() const { return _escape; } 168 EscapeState escape_state() const { return _escape; }
157 NodeType node_type() const { return _type;} 169 NodeType node_type() const { return _type;}
158 int offset() { return _offset;} 170 int offset() { return _offset;}
159 171
180 192
181 }; 193 };
182 194
183 class ConnectionGraph: public ResourceObj { 195 class ConnectionGraph: public ResourceObj {
184 private: 196 private:
185 enum { 197 GrowableArray<PointsToNode>* _nodes; // Connection graph nodes indexed
186 INITIAL_NODE_COUNT = 100 // initial size of _nodes array 198 // by ideal node index.
187 }; 199
188 200 Unique_Node_List _delayed_worklist; // Nodes to be processed before
189 201 // the call build_connection_graph().
190 GrowableArray<PointsToNode>* _nodes; // connection graph nodes Indexed by ideal 202
191 // node index 203 VectorSet _processed; // Records which nodes have been
192 Unique_Node_List _deferred; // Phi's to be processed after parsing 204 // processed.
193 VectorSet _processed; // records which nodes have been processed 205
194 bool _collecting; // indicates whether escape information is 206 bool _collecting; // Indicates whether escape information
195 // still being collected. If false, no new 207 // is still being collected. If false,
196 // nodes will be processed 208 // no new nodes will be processed.
197 uint _phantom_object; // index of globally escaping object that 209
198 // pointer values loaded from a field which 210 bool _has_allocations; // Indicates whether method has any
199 // has not been set are assumed to point to 211 // non-escaping allocations.
200 Compile * _compile; // Compile object for current compilation 212
213 uint _phantom_object; // Index of globally escaping object
214 // that pointer values loaded from
215 // a field which has not been set
216 // are assumed to point to.
217
218 Compile * _compile; // Compile object for current compilation
201 219
202 // address of an element in _nodes. Used when the element is to be modified 220 // address of an element in _nodes. Used when the element is to be modified
203 PointsToNode *ptnode_adr(uint idx) { 221 PointsToNode *ptnode_adr(uint idx) {
204 if ((uint)_nodes->length() <= idx) { 222 if ((uint)_nodes->length() <= idx) {
205 // expand _nodes array 223 // expand _nodes array
206 PointsToNode dummy = _nodes->at_grow(idx); 224 PointsToNode dummy = _nodes->at_grow(idx);
207 } 225 }
208 return _nodes->adr_at(idx); 226 return _nodes->adr_at(idx);
209 } 227 }
210 228
229 // Add node to ConnectionGraph.
230 void add_node(Node *n, PointsToNode::NodeType nt, PointsToNode::EscapeState es, bool done);
231
211 // offset of a field reference 232 // offset of a field reference
212 int type_to_offset(const Type *t); 233 int address_offset(Node* adr, PhaseTransform *phase);
213 234
214 // compute the escape state for arguments to a call 235 // compute the escape state for arguments to a call
215 void process_call_arguments(CallNode *call, PhaseTransform *phase); 236 void process_call_arguments(CallNode *call, PhaseTransform *phase);
216 237
217 // compute the escape state for the return value of a call 238 // compute the escape state for the return value of a call
218 void process_call_result(ProjNode *resproj, PhaseTransform *phase); 239 void process_call_result(ProjNode *resproj, PhaseTransform *phase);
219 240
220 // compute the escape state of a Phi. This may be called multiple 241 // Populate Connection Graph with Ideal nodes.
221 // times as new inputs are added to the Phi. 242 void record_for_escape_analysis(Node *n, PhaseTransform *phase);
222 void process_phi_escape(PhiNode *phi, PhaseTransform *phase); 243
223 244 // Build Connection Graph and set nodes escape state.
224 // compute the escape state of an ideal node. 245 void build_connection_graph(Node *n, PhaseTransform *phase);
225 void record_escape_work(Node *n, PhaseTransform *phase);
226 246
227 // walk the connection graph starting at the node corresponding to "n" and 247 // walk the connection graph starting at the node corresponding to "n" and
228 // add the index of everything it could point to, to "ptset". This may cause 248 // add the index of everything it could point to, to "ptset". This may cause
229 // Phi's encountered to get (re)processed (which requires "phase".) 249 // Phi's encountered to get (re)processed (which requires "phase".)
230 void PointsTo(VectorSet &ptset, Node * n, PhaseTransform *phase); 250 void PointsTo(VectorSet &ptset, Node * n, PhaseTransform *phase);
239 // Add an edge to node given by "to_i" from any field of adr_i whose offset 259 // Add an edge to node given by "to_i" from any field of adr_i whose offset
240 // matches "offset" A deferred edge is added if to_i is a LocalVar, and 260 // matches "offset" A deferred edge is added if to_i is a LocalVar, and
241 // a pointsto edge is added if it is a JavaObject 261 // a pointsto edge is added if it is a JavaObject
242 void add_edge_from_fields(uint adr, uint to_i, int offs); 262 void add_edge_from_fields(uint adr, uint to_i, int offs);
243 263
244 // Add a deferred edge from node given by "from_i" to any field of adr_i whose offset 264 // Add a deferred edge from node given by "from_i" to any field
245 // matches "offset" 265 // of adr_i whose offset matches "offset"
246 void add_deferred_edge_to_fields(uint from_i, uint adr, int offs); 266 void add_deferred_edge_to_fields(uint from_i, uint adr, int offs);
247 267
248 268
249 // Remove outgoing deferred edges from the node referenced by "ni". 269 // Remove outgoing deferred edges from the node referenced by "ni".
250 // Any outgoing edges from the target of the deferred edge are copied 270 // Any outgoing edges from the target of the deferred edge are copied
260 // allocation - CheckCastPP of the allocation 280 // allocation - CheckCastPP of the allocation
261 void split_AddP(Node *addp, Node *base, PhaseGVN *igvn); 281 void split_AddP(Node *addp, Node *base, PhaseGVN *igvn);
262 PhiNode *create_split_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *> &orig_phi_worklist, PhaseGVN *igvn, bool &new_created); 282 PhiNode *create_split_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *> &orig_phi_worklist, PhaseGVN *igvn, bool &new_created);
263 PhiNode *split_memory_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *> &orig_phi_worklist, PhaseGVN *igvn); 283 PhiNode *split_memory_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *> &orig_phi_worklist, PhaseGVN *igvn);
264 Node *find_mem(Node *mem, int alias_idx, PhaseGVN *igvn); 284 Node *find_mem(Node *mem, int alias_idx, PhaseGVN *igvn);
285 Node *find_inst_mem(Node *mem, int alias_idx,GrowableArray<PhiNode *> &orig_phi_worklist, PhaseGVN *igvn);
286
265 // Propagate unique types created for unescaped allocated objects 287 // Propagate unique types created for unescaped allocated objects
266 // through the graph 288 // through the graph
267 void split_unique_types(GrowableArray<Node *> &alloc_worklist); 289 void split_unique_types(GrowableArray<Node *> &alloc_worklist);
268 290
269 // manage entries in _node_map 291 // manage entries in _node_map
283 } 305 }
284 306
285 // Set the escape state of a node 307 // Set the escape state of a node
286 void set_escape_state(uint ni, PointsToNode::EscapeState es); 308 void set_escape_state(uint ni, PointsToNode::EscapeState es);
287 309
288 // bypass any casts and return the node they refer to
289 Node * skip_casts(Node *n);
290
291 // Get Compile object for current compilation. 310 // Get Compile object for current compilation.
292 Compile *C() const { return _compile; } 311 Compile *C() const { return _compile; }
293 312
294 public: 313 public:
295 ConnectionGraph(Compile *C); 314 ConnectionGraph(Compile *C);
296 315
297 // record a Phi for later processing. 316 // Compute the escape information
298 void record_for_escape_analysis(Node *n);
299
300 // process a node and fill in its connection graph node
301 void record_escape(Node *n, PhaseTransform *phase);
302
303 // All nodes have been recorded, compute the escape information
304 void compute_escape(); 317 void compute_escape();
305 318
306 // escape state of a node 319 // escape state of a node
307 PointsToNode::EscapeState escape_state(Node *n, PhaseTransform *phase); 320 PointsToNode::EscapeState escape_state(Node *n, PhaseTransform *phase);
321 // other information we have collected
322 bool is_scalar_replaceable(Node *n) {
323 if (_collecting)
324 return false;
325 PointsToNode ptn = _nodes->at_grow(n->_idx);
326 return ptn.escape_state() == PointsToNode::NoEscape && ptn._scalar_replaceable;
327 }
308 328
309 bool hidden_alias(Node *n) { 329 bool hidden_alias(Node *n) {
310 if (_collecting) 330 if (_collecting)
311 return true; 331 return true;
312 PointsToNode ptn = _nodes->at_grow(n->_idx); 332 PointsToNode ptn = _nodes->at_grow(n->_idx);

mercurial