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 |