Mercurial > hg > truffle
comparison src/share/vm/opto/escape.hpp @ 4137:04b9a2566eec
Merge with hsx23/hotspot.
author | Thomas Wuerthinger <thomas.wuerthinger@oracle.com> |
---|---|
date | Sat, 17 Dec 2011 21:40:27 +0100 |
parents | cc81b9c09bbb |
children | ee138854b3a6 |
comparison
equal
deleted
inserted
replaced
3737:9dc19b7d89a3 | 4137:04b9a2566eec |
---|---|
72 // to the static memory. | 72 // to the static memory. |
73 // | 73 // |
74 // C2 does not have local variables. However for the purposes of constructing | 74 // C2 does not have local variables. However for the purposes of constructing |
75 // the connection graph, the following IR nodes are treated as local variables: | 75 // the connection graph, the following IR nodes are treated as local variables: |
76 // Phi (pointer values) | 76 // Phi (pointer values) |
77 // LoadP | 77 // LoadP, LoadN |
78 // Proj#5 (value returned from callnodes including allocations) | 78 // Proj#5 (value returned from callnodes including allocations) |
79 // CheckCastPP, CastPP | 79 // CheckCastPP, CastPP |
80 // | 80 // |
81 // The LoadP, Proj and CheckCastPP behave like variables assigned to only once. | 81 // The LoadP, Proj and CheckCastPP behave like variables assigned to only once. |
82 // Only a Phi can have multiple assignments. Each input to a Phi is treated | 82 // Only a Phi can have multiple assignments. Each input to a Phi is treated |
83 // as an assignment to it. | 83 // as an assignment to it. |
84 // | 84 // |
85 // The following node types are JavaObject: | 85 // The following node types are JavaObject: |
86 // | 86 // |
87 // top() | 87 // phantom_object (general globally escaped object) |
88 // Allocate | 88 // Allocate |
89 // AllocateArray | 89 // AllocateArray |
90 // Parm (for incoming arguments) | 90 // Parm (for incoming arguments) |
91 // CastX2P ("unsafe" operations) | 91 // CastX2P ("unsafe" operations) |
92 // CreateEx | 92 // CreateEx |
93 // ConP | 93 // ConP |
94 // LoadKlass | 94 // LoadKlass |
95 // ThreadLocal | 95 // ThreadLocal |
96 // CallStaticJava (which returns Object) | |
96 // | 97 // |
97 // AddP nodes are fields. | 98 // AddP nodes are fields. |
98 // | 99 // |
99 // After building the graph, a pass is made over the nodes, deleting deferred | 100 // After building the graph, a pass is made over the nodes, deleting deferred |
100 // nodes and copying the edges from the target of the deferred edge to the | 101 // nodes and copying the edges from the target of the deferred edge to the |
128 Field = 3 | 129 Field = 3 |
129 } NodeType; | 130 } NodeType; |
130 | 131 |
131 typedef enum { | 132 typedef enum { |
132 UnknownEscape = 0, | 133 UnknownEscape = 0, |
133 NoEscape = 1, // A scalar replaceable object with unique type. | 134 NoEscape = 1, // An object does not escape method or thread and it is |
134 ArgEscape = 2, // An object passed as argument or referenced by | 135 // not passed to call. It could be replaced with scalar. |
135 // argument (and not globally escape during call). | 136 ArgEscape = 2, // An object does not escape method or thread but it is |
136 GlobalEscape = 3 // An object escapes the method and thread. | 137 // passed as argument to call or referenced by argument |
138 // and it does not escape during call. | |
139 GlobalEscape = 3 // An object escapes the method or thread. | |
137 } EscapeState; | 140 } EscapeState; |
138 | 141 |
139 typedef enum { | 142 typedef enum { |
140 UnknownEdge = 0, | 143 UnknownEdge = 0, |
141 PointsToEdge = 1, | 144 PointsToEdge = 1, |
151 INITIAL_EDGE_COUNT = 4 | 154 INITIAL_EDGE_COUNT = 4 |
152 }; | 155 }; |
153 | 156 |
154 NodeType _type; | 157 NodeType _type; |
155 EscapeState _escape; | 158 EscapeState _escape; |
156 GrowableArray<uint>* _edges; // outgoing edges | 159 GrowableArray<uint>* _edges; // outgoing edges |
160 Node* _node; // Ideal node corresponding to this PointsTo node. | |
161 int _offset; // Object fields offsets. | |
162 bool _scalar_replaceable; // Not escaped object could be replaced with scalar | |
163 bool _has_unknown_ptr; // Has edge to phantom_object | |
157 | 164 |
158 public: | 165 public: |
159 Node* _node; // Ideal node corresponding to this PointsTo node. | |
160 int _offset; // Object fields offsets. | |
161 bool _scalar_replaceable;// Not escaped object could be replaced with scalar | |
162 bool _hidden_alias; // This node is an argument to a function. | |
163 // which may return it creating a hidden alias. | |
164 | |
165 PointsToNode(): | 166 PointsToNode(): |
166 _type(UnknownType), | 167 _type(UnknownType), |
167 _escape(UnknownEscape), | 168 _escape(UnknownEscape), |
168 _edges(NULL), | 169 _edges(NULL), |
169 _node(NULL), | 170 _node(NULL), |
170 _offset(-1), | 171 _offset(-1), |
171 _scalar_replaceable(true), | 172 _has_unknown_ptr(false), |
172 _hidden_alias(false) {} | 173 _scalar_replaceable(true) {} |
173 | 174 |
174 | 175 |
175 EscapeState escape_state() const { return _escape; } | 176 EscapeState escape_state() const { return _escape; } |
176 NodeType node_type() const { return _type;} | 177 NodeType node_type() const { return _type;} |
177 int offset() { return _offset;} | 178 int offset() { return _offset;} |
179 bool scalar_replaceable() { return _scalar_replaceable;} | |
180 bool has_unknown_ptr() { return _has_unknown_ptr;} | |
178 | 181 |
179 void set_offset(int offs) { _offset = offs;} | 182 void set_offset(int offs) { _offset = offs;} |
180 void set_escape_state(EscapeState state) { _escape = state; } | 183 void set_escape_state(EscapeState state) { _escape = state; } |
181 void set_node_type(NodeType ntype) { | 184 void set_node_type(NodeType ntype) { |
182 assert(_type == UnknownType || _type == ntype, "Can't change node type"); | 185 assert(_type == UnknownType || _type == ntype, "Can't change node type"); |
183 _type = ntype; | 186 _type = ntype; |
184 } | 187 } |
188 void set_scalar_replaceable(bool v) { _scalar_replaceable = v; } | |
189 void set_has_unknown_ptr() { _has_unknown_ptr = true; } | |
185 | 190 |
186 // count of outgoing edges | 191 // count of outgoing edges |
187 uint edge_count() const { return (_edges == NULL) ? 0 : _edges->length(); } | 192 uint edge_count() const { return (_edges == NULL) ? 0 : _edges->length(); } |
188 | 193 |
189 // node index of target of outgoing edge "e" | 194 // node index of target of outgoing edge "e" |
231 | 236 |
232 uint _phantom_object; // Index of globally escaping object | 237 uint _phantom_object; // Index of globally escaping object |
233 // that pointer values loaded from | 238 // that pointer values loaded from |
234 // a field which has not been set | 239 // a field which has not been set |
235 // are assumed to point to. | 240 // are assumed to point to. |
236 uint _oop_null; // ConP(#NULL) | 241 uint _oop_null; // ConP(#NULL)->_idx |
237 uint _noop_null; // ConN(#NULL) | 242 uint _noop_null; // ConN(#NULL)->_idx |
243 Node* _pcmp_neq; // ConI(#CC_GT) | |
244 Node* _pcmp_eq; // ConI(#CC_EQ) | |
238 | 245 |
239 Compile * _compile; // Compile object for current compilation | 246 Compile * _compile; // Compile object for current compilation |
240 PhaseIterGVN * _igvn; // Value numbering | 247 PhaseIterGVN * _igvn; // Value numbering |
241 | 248 |
242 // Address of an element in _nodes. Used when the element is to be modified | 249 // Address of an element in _nodes. Used when the element is to be modified |
244 // There should be no new ideal nodes during ConnectionGraph build, | 251 // There should be no new ideal nodes during ConnectionGraph build, |
245 // growableArray::adr_at() will throw assert otherwise. | 252 // growableArray::adr_at() will throw assert otherwise. |
246 return _nodes.adr_at(idx); | 253 return _nodes.adr_at(idx); |
247 } | 254 } |
248 uint nodes_size() const { return _nodes.length(); } | 255 uint nodes_size() const { return _nodes.length(); } |
256 | |
257 bool is_null_ptr(uint idx) const { return (idx == _noop_null || idx == _oop_null); } | |
249 | 258 |
250 // Add node to ConnectionGraph. | 259 // Add node to ConnectionGraph. |
251 void add_node(Node *n, PointsToNode::NodeType nt, PointsToNode::EscapeState es, bool done); | 260 void add_node(Node *n, PointsToNode::NodeType nt, PointsToNode::EscapeState es, bool done); |
252 | 261 |
253 // offset of a field reference | 262 // offset of a field reference |
328 Node *phi = _node_map[idx]; | 337 Node *phi = _node_map[idx]; |
329 return (phi == NULL) ? NULL : phi->as_Phi(); | 338 return (phi == NULL) ? NULL : phi->as_Phi(); |
330 } | 339 } |
331 | 340 |
332 // Notify optimizer that a node has been modified | 341 // Notify optimizer that a node has been modified |
333 // Node: This assumes that escape analysis is run before | |
334 // PhaseIterGVN creation | |
335 void record_for_optimizer(Node *n) { | 342 void record_for_optimizer(Node *n) { |
336 _igvn->_worklist.push(n); | 343 _igvn->_worklist.push(n); |
344 _igvn->add_users_to_worklist(n); | |
337 } | 345 } |
338 | 346 |
339 // Set the escape state of a node | 347 // Set the escape state of a node |
340 void set_escape_state(uint ni, PointsToNode::EscapeState es); | 348 void set_escape_state(uint ni, PointsToNode::EscapeState es); |
341 | 349 |
350 // Find fields initializing values for allocations. | |
351 void find_init_values(Node* n, VectorSet* visited, PhaseTransform* phase); | |
352 | |
342 // Adjust escape state after Connection Graph is built. | 353 // Adjust escape state after Connection Graph is built. |
343 void adjust_escape_state(int nidx, PhaseTransform* phase); | 354 void adjust_escape_state(Node* n); |
355 | |
356 // Propagate escape states to referenced nodes. | |
357 bool propagate_escape_state(GrowableArray<int>* cg_worklist, | |
358 GrowableArray<uint>* worklist, | |
359 PointsToNode::EscapeState esc_state); | |
360 | |
361 // Optimize objects compare. | |
362 Node* optimize_ptr_compare(Node* n); | |
344 | 363 |
345 // Compute the escape information | 364 // Compute the escape information |
346 bool compute_escape(); | 365 bool compute_escape(); |
347 | 366 |
348 public: | 367 public: |
354 // Perform escape analysis | 373 // Perform escape analysis |
355 static void do_analysis(Compile *C, PhaseIterGVN *igvn); | 374 static void do_analysis(Compile *C, PhaseIterGVN *igvn); |
356 | 375 |
357 // escape state of a node | 376 // escape state of a node |
358 PointsToNode::EscapeState escape_state(Node *n); | 377 PointsToNode::EscapeState escape_state(Node *n); |
359 | |
360 // other information we have collected | |
361 bool is_scalar_replaceable(Node *n) { | |
362 if (_collecting || (n->_idx >= nodes_size())) | |
363 return false; | |
364 PointsToNode* ptn = ptnode_adr(n->_idx); | |
365 return ptn->escape_state() == PointsToNode::NoEscape && ptn->_scalar_replaceable; | |
366 } | |
367 | |
368 bool hidden_alias(Node *n) { | |
369 if (_collecting || (n->_idx >= nodes_size())) | |
370 return true; | |
371 PointsToNode* ptn = ptnode_adr(n->_idx); | |
372 return (ptn->escape_state() != PointsToNode::NoEscape) || ptn->_hidden_alias; | |
373 } | |
374 | 378 |
375 #ifndef PRODUCT | 379 #ifndef PRODUCT |
376 void dump(); | 380 void dump(); |
377 #endif | 381 #endif |
378 }; | 382 }; |