Mercurial > hg > graal-jvmci-8
comparison src/share/vm/opto/escape.hpp @ 20585:90297adbda9d
8041984: CompilerThread seems to occupy all CPU in a very rare situation
Summary: Add new timeout checks to EA.
Reviewed-by: iveresov, drchase
author | kvn |
---|---|
date | Fri, 24 Oct 2014 10:28:19 -0700 |
parents | 7eca5de9e0b6 |
children |
comparison
equal
deleted
inserted
replaced
20584:ef9eda2c1abe | 20585:90297adbda9d |
---|---|
123 class JavaObjectNode; | 123 class JavaObjectNode; |
124 class LocalVarNode; | 124 class LocalVarNode; |
125 class FieldNode; | 125 class FieldNode; |
126 class ArraycopyNode; | 126 class ArraycopyNode; |
127 | 127 |
128 class ConnectionGraph; | |
129 | |
128 // ConnectionGraph nodes | 130 // ConnectionGraph nodes |
129 class PointsToNode : public ResourceObj { | 131 class PointsToNode : public ResourceObj { |
130 GrowableArray<PointsToNode*> _edges; // List of nodes this node points to | 132 GrowableArray<PointsToNode*> _edges; // List of nodes this node points to |
131 GrowableArray<PointsToNode*> _uses; // List of nodes which point to this node | 133 GrowableArray<PointsToNode*> _uses; // List of nodes which point to this node |
132 | 134 |
135 u1 _escape; // EscapeState of object | 137 u1 _escape; // EscapeState of object |
136 u1 _fields_escape; // EscapeState of object's fields | 138 u1 _fields_escape; // EscapeState of object's fields |
137 | 139 |
138 Node* const _node; // Ideal node corresponding to this PointsTo node. | 140 Node* const _node; // Ideal node corresponding to this PointsTo node. |
139 const int _idx; // Cached ideal node's _idx | 141 const int _idx; // Cached ideal node's _idx |
142 const uint _pidx; // Index of this node | |
140 | 143 |
141 public: | 144 public: |
142 typedef enum { | 145 typedef enum { |
143 UnknownType = 0, | 146 UnknownType = 0, |
144 JavaObject = 1, | 147 JavaObject = 1, |
163 ArraycopySrc = 4, // Has edge from Arraycopy node | 166 ArraycopySrc = 4, // Has edge from Arraycopy node |
164 ArraycopyDst = 8 // Has edge to Arraycopy node | 167 ArraycopyDst = 8 // Has edge to Arraycopy node |
165 } NodeFlags; | 168 } NodeFlags; |
166 | 169 |
167 | 170 |
168 PointsToNode(Compile *C, Node* n, EscapeState es, NodeType type): | 171 inline PointsToNode(ConnectionGraph* CG, Node* n, EscapeState es, NodeType type); |
169 _edges(C->comp_arena(), 2, 0, NULL), | 172 |
170 _uses (C->comp_arena(), 2, 0, NULL), | 173 uint pidx() const { return _pidx; } |
171 _node(n), | |
172 _idx(n->_idx), | |
173 _type((u1)type), | |
174 _escape((u1)es), | |
175 _fields_escape((u1)es), | |
176 _flags(ScalarReplaceable) { | |
177 assert(n != NULL && es != UnknownEscape, "sanity"); | |
178 } | |
179 | 174 |
180 Node* ideal_node() const { return _node; } | 175 Node* ideal_node() const { return _node; } |
181 int idx() const { return _idx; } | 176 int idx() const { return _idx; } |
182 | 177 |
183 bool is_JavaObject() const { return _type == (u1)JavaObject; } | 178 bool is_JavaObject() const { return _type == (u1)JavaObject; } |
241 | 236 |
242 }; | 237 }; |
243 | 238 |
244 class LocalVarNode: public PointsToNode { | 239 class LocalVarNode: public PointsToNode { |
245 public: | 240 public: |
246 LocalVarNode(Compile *C, Node* n, EscapeState es): | 241 LocalVarNode(ConnectionGraph *CG, Node* n, EscapeState es): |
247 PointsToNode(C, n, es, LocalVar) {} | 242 PointsToNode(CG, n, es, LocalVar) {} |
248 }; | 243 }; |
249 | 244 |
250 class JavaObjectNode: public PointsToNode { | 245 class JavaObjectNode: public PointsToNode { |
251 public: | 246 public: |
252 JavaObjectNode(Compile *C, Node* n, EscapeState es): | 247 JavaObjectNode(ConnectionGraph *CG, Node* n, EscapeState es): |
253 PointsToNode(C, n, es, JavaObject) { | 248 PointsToNode(CG, n, es, JavaObject) { |
254 if (es > NoEscape) | 249 if (es > NoEscape) |
255 set_scalar_replaceable(false); | 250 set_scalar_replaceable(false); |
256 } | 251 } |
257 }; | 252 }; |
258 | 253 |
260 GrowableArray<PointsToNode*> _bases; // List of JavaObject nodes which point to this node | 255 GrowableArray<PointsToNode*> _bases; // List of JavaObject nodes which point to this node |
261 const int _offset; // Field's offset. | 256 const int _offset; // Field's offset. |
262 const bool _is_oop; // Field points to object | 257 const bool _is_oop; // Field points to object |
263 bool _has_unknown_base; // Has phantom_object base | 258 bool _has_unknown_base; // Has phantom_object base |
264 public: | 259 public: |
265 FieldNode(Compile *C, Node* n, EscapeState es, int offs, bool is_oop): | 260 FieldNode(ConnectionGraph *CG, Node* n, EscapeState es, int offs, bool is_oop): |
266 PointsToNode(C, n, es, Field), | 261 PointsToNode(CG, n, es, Field), |
267 _offset(offs), _is_oop(is_oop), | 262 _offset(offs), _is_oop(is_oop), |
268 _has_unknown_base(false) {} | 263 _has_unknown_base(false) {} |
269 | 264 |
270 int offset() const { return _offset;} | 265 int offset() const { return _offset;} |
271 bool is_oop() const { return _is_oop;} | 266 bool is_oop() const { return _is_oop;} |
282 | 277 |
283 }; | 278 }; |
284 | 279 |
285 class ArraycopyNode: public PointsToNode { | 280 class ArraycopyNode: public PointsToNode { |
286 public: | 281 public: |
287 ArraycopyNode(Compile *C, Node* n, EscapeState es): | 282 ArraycopyNode(ConnectionGraph *CG, Node* n, EscapeState es): |
288 PointsToNode(C, n, es, Arraycopy) {} | 283 PointsToNode(CG, n, es, Arraycopy) {} |
289 }; | 284 }; |
290 | 285 |
291 // Iterators for PointsTo node's edges: | 286 // Iterators for PointsTo node's edges: |
292 // for (EdgeIterator i(n); i.has_next(); i.next()) { | 287 // for (EdgeIterator i(n); i.has_next(); i.next()) { |
293 // PointsToNode* u = i.get(); | 288 // PointsToNode* u = i.get(); |
321 inline PointsToNode* get() const { return ((PointsToNode*)node)->as_Field()->base(i); } | 316 inline PointsToNode* get() const { return ((PointsToNode*)node)->as_Field()->base(i); } |
322 }; | 317 }; |
323 | 318 |
324 | 319 |
325 class ConnectionGraph: public ResourceObj { | 320 class ConnectionGraph: public ResourceObj { |
321 friend class PointsToNode; | |
326 private: | 322 private: |
327 GrowableArray<PointsToNode*> _nodes; // Map from ideal nodes to | 323 GrowableArray<PointsToNode*> _nodes; // Map from ideal nodes to |
328 // ConnectionGraph nodes. | 324 // ConnectionGraph nodes. |
329 | 325 |
330 GrowableArray<PointsToNode*> _worklist; // Nodes to be processed | 326 GrowableArray<PointsToNode*> _worklist; // Nodes to be processed |
327 VectorSet _in_worklist; | |
328 uint _next_pidx; | |
331 | 329 |
332 bool _collecting; // Indicates whether escape information | 330 bool _collecting; // Indicates whether escape information |
333 // is still being collected. If false, | 331 // is still being collected. If false, |
334 // no new nodes will be processed. | 332 // no new nodes will be processed. |
335 | 333 |
350 // There should be no new ideal nodes during ConnectionGraph build, | 348 // There should be no new ideal nodes during ConnectionGraph build, |
351 // growableArray::at() will throw assert otherwise. | 349 // growableArray::at() will throw assert otherwise. |
352 return _nodes.at(idx); | 350 return _nodes.at(idx); |
353 } | 351 } |
354 uint nodes_size() const { return _nodes.length(); } | 352 uint nodes_size() const { return _nodes.length(); } |
353 | |
354 uint next_pidx() { return _next_pidx++; } | |
355 | 355 |
356 // Add nodes to ConnectionGraph. | 356 // Add nodes to ConnectionGraph. |
357 void add_local_var(Node* n, PointsToNode::EscapeState es); | 357 void add_local_var(Node* n, PointsToNode::EscapeState es); |
358 void add_java_object(Node* n, PointsToNode::EscapeState es); | 358 void add_java_object(Node* n, PointsToNode::EscapeState es); |
359 void add_field(Node* n, PointsToNode::EscapeState es, int offset); | 359 void add_field(Node* n, PointsToNode::EscapeState es, int offset); |
394 | 394 |
395 // Add all references to this JavaObject node. | 395 // Add all references to this JavaObject node. |
396 int add_java_object_edges(JavaObjectNode* jobj, bool populate_worklist); | 396 int add_java_object_edges(JavaObjectNode* jobj, bool populate_worklist); |
397 | 397 |
398 // Put node on worklist if it is (or was) not there. | 398 // Put node on worklist if it is (or was) not there. |
399 void add_to_worklist(PointsToNode* pt) { | 399 inline void add_to_worklist(PointsToNode* pt) { |
400 _worklist.push(pt); | 400 PointsToNode* ptf = pt; |
401 return; | 401 uint pidx_bias = 0; |
402 if (PointsToNode::is_base_use(pt)) { | |
403 // Create a separate entry in _in_worklist for a marked base edge | |
404 // because _worklist may have an entry for a normal edge pointing | |
405 // to the same node. To separate them use _next_pidx as bias. | |
406 ptf = PointsToNode::get_use_node(pt)->as_Field(); | |
407 pidx_bias = _next_pidx; | |
408 } | |
409 if (!_in_worklist.test_set(ptf->pidx() + pidx_bias)) { | |
410 _worklist.append(pt); | |
411 } | |
402 } | 412 } |
403 | 413 |
404 // Put on worklist all uses of this node. | 414 // Put on worklist all uses of this node. |
405 void add_uses_to_worklist(PointsToNode* pt) { | 415 inline void add_uses_to_worklist(PointsToNode* pt) { |
406 for (UseIterator i(pt); i.has_next(); i.next()) | 416 for (UseIterator i(pt); i.has_next(); i.next()) { |
407 _worklist.push(i.get()); | 417 add_to_worklist(i.get()); |
418 } | |
408 } | 419 } |
409 | 420 |
410 // Put on worklist all field's uses and related field nodes. | 421 // Put on worklist all field's uses and related field nodes. |
411 void add_field_uses_to_worklist(FieldNode* field); | 422 void add_field_uses_to_worklist(FieldNode* field); |
412 | 423 |
515 } | 526 } |
516 add_edge(ptnode_adr(n->_idx), ptn); | 527 add_edge(ptnode_adr(n->_idx), ptn); |
517 } | 528 } |
518 // Helper functions | 529 // Helper functions |
519 bool is_oop_field(Node* n, int offset, bool* unsafe); | 530 bool is_oop_field(Node* n, int offset, bool* unsafe); |
520 static Node* get_addp_base(Node *addp); | 531 static Node* get_addp_base(Node *addp); |
521 static Node* find_second_addp(Node* addp, Node* n); | 532 static Node* find_second_addp(Node* addp, Node* n); |
522 // offset of a field reference | 533 // offset of a field reference |
523 int address_offset(Node* adr, PhaseTransform *phase); | 534 int address_offset(Node* adr, PhaseTransform *phase); |
524 | 535 |
525 | 536 |
526 // Propagate unique types created for unescaped allocated objects | 537 // Propagate unique types created for unescaped allocated objects |
585 #ifndef PRODUCT | 596 #ifndef PRODUCT |
586 void dump(GrowableArray<PointsToNode*>& ptnodes_worklist); | 597 void dump(GrowableArray<PointsToNode*>& ptnodes_worklist); |
587 #endif | 598 #endif |
588 }; | 599 }; |
589 | 600 |
601 inline PointsToNode::PointsToNode(ConnectionGraph *CG, Node* n, EscapeState es, NodeType type): | |
602 _edges(CG->_compile->comp_arena(), 2, 0, NULL), | |
603 _uses (CG->_compile->comp_arena(), 2, 0, NULL), | |
604 _node(n), | |
605 _idx(n->_idx), | |
606 _pidx(CG->next_pidx()), | |
607 _type((u1)type), | |
608 _escape((u1)es), | |
609 _fields_escape((u1)es), | |
610 _flags(ScalarReplaceable) { | |
611 assert(n != NULL && es != UnknownEscape, "sanity"); | |
612 } | |
613 | |
590 #endif // SHARE_VM_OPTO_ESCAPE_HPP | 614 #endif // SHARE_VM_OPTO_ESCAPE_HPP |