280 #endif |
280 #endif |
281 } |
281 } |
282 return has_non_escaping_obj; |
282 return has_non_escaping_obj; |
283 } |
283 } |
284 |
284 |
|
285 // Utility function for nodes that load an object |
|
286 void ConnectionGraph::add_objload_to_connection_graph(Node *n, Unique_Node_List *delayed_worklist) { |
|
287 // Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because |
|
288 // ThreadLocal has RawPtr type. |
|
289 const Type* t = _igvn->type(n); |
|
290 if (t->make_ptr() != NULL) { |
|
291 Node* adr = n->in(MemNode::Address); |
|
292 #ifdef ASSERT |
|
293 if (!adr->is_AddP()) { |
|
294 assert(_igvn->type(adr)->isa_rawptr(), "sanity"); |
|
295 } else { |
|
296 assert((ptnode_adr(adr->_idx) == NULL || |
|
297 ptnode_adr(adr->_idx)->as_Field()->is_oop()), "sanity"); |
|
298 } |
|
299 #endif |
|
300 add_local_var_and_edge(n, PointsToNode::NoEscape, |
|
301 adr, delayed_worklist); |
|
302 } |
|
303 } |
|
304 |
285 // Populate Connection Graph with PointsTo nodes and create simple |
305 // Populate Connection Graph with PointsTo nodes and create simple |
286 // connection graph edges. |
306 // connection graph edges. |
287 void ConnectionGraph::add_node_to_connection_graph(Node *n, Unique_Node_List *delayed_worklist) { |
307 void ConnectionGraph::add_node_to_connection_graph(Node *n, Unique_Node_List *delayed_worklist) { |
288 assert(!_verify, "this method sould not be called for verification"); |
308 assert(!_verify, "this method sould not be called for verification"); |
289 PhaseGVN* igvn = _igvn; |
309 PhaseGVN* igvn = _igvn; |
385 break; |
405 break; |
386 } |
406 } |
387 case Op_LoadP: |
407 case Op_LoadP: |
388 case Op_LoadN: |
408 case Op_LoadN: |
389 case Op_LoadPLocked: { |
409 case Op_LoadPLocked: { |
390 // Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because |
410 add_objload_to_connection_graph(n, delayed_worklist); |
391 // ThreadLocal has RawPrt type. |
|
392 const Type* t = igvn->type(n); |
|
393 if (t->make_ptr() != NULL) { |
|
394 Node* adr = n->in(MemNode::Address); |
|
395 #ifdef ASSERT |
|
396 if (!adr->is_AddP()) { |
|
397 assert(igvn->type(adr)->isa_rawptr(), "sanity"); |
|
398 } else { |
|
399 assert((ptnode_adr(adr->_idx) == NULL || |
|
400 ptnode_adr(adr->_idx)->as_Field()->is_oop()), "sanity"); |
|
401 } |
|
402 #endif |
|
403 add_local_var_and_edge(n, PointsToNode::NoEscape, |
|
404 adr, delayed_worklist); |
|
405 } |
|
406 break; |
411 break; |
407 } |
412 } |
408 case Op_Parm: { |
413 case Op_Parm: { |
409 map_ideal_node(n, phantom_obj); |
414 map_ideal_node(n, phantom_obj); |
410 break; |
415 break; |
415 map_ideal_node(n, phantom_obj); // Result is unknown |
420 map_ideal_node(n, phantom_obj); // Result is unknown |
416 break; |
421 break; |
417 } |
422 } |
418 case Op_Phi: { |
423 case Op_Phi: { |
419 // Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because |
424 // Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because |
420 // ThreadLocal has RawPrt type. |
425 // ThreadLocal has RawPtr type. |
421 const Type* t = n->as_Phi()->type(); |
426 const Type* t = n->as_Phi()->type(); |
422 if (t->make_ptr() != NULL) { |
427 if (t->make_ptr() != NULL) { |
423 add_local_var(n, PointsToNode::NoEscape); |
428 add_local_var(n, PointsToNode::NoEscape); |
424 // Do not add edges during first iteration because some could be |
429 // Do not add edges during first iteration because some could be |
425 // not defined yet. |
430 // not defined yet. |
443 // Treat Return value as LocalVar with GlobalEscape escape state. |
448 // Treat Return value as LocalVar with GlobalEscape escape state. |
444 add_local_var_and_edge(n, PointsToNode::GlobalEscape, |
449 add_local_var_and_edge(n, PointsToNode::GlobalEscape, |
445 n->in(TypeFunc::Parms), delayed_worklist); |
450 n->in(TypeFunc::Parms), delayed_worklist); |
446 } |
451 } |
447 break; |
452 break; |
|
453 } |
|
454 case Op_GetAndSetP: |
|
455 case Op_GetAndSetN: { |
|
456 add_objload_to_connection_graph(n, delayed_worklist); |
|
457 // fallthrough |
448 } |
458 } |
449 case Op_StoreP: |
459 case Op_StoreP: |
450 case Op_StoreN: |
460 case Op_StoreN: |
451 case Op_StorePConditional: |
461 case Op_StorePConditional: |
452 case Op_CompareAndSwapP: |
462 case Op_CompareAndSwapP: |
583 } |
593 } |
584 case Op_LoadP: |
594 case Op_LoadP: |
585 case Op_LoadN: |
595 case Op_LoadN: |
586 case Op_LoadPLocked: { |
596 case Op_LoadPLocked: { |
587 // Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because |
597 // Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because |
588 // ThreadLocal has RawPrt type. |
598 // ThreadLocal has RawPtr type. |
589 const Type* t = _igvn->type(n); |
599 const Type* t = _igvn->type(n); |
590 if (t->make_ptr() != NULL) { |
600 if (t->make_ptr() != NULL) { |
591 Node* adr = n->in(MemNode::Address); |
601 Node* adr = n->in(MemNode::Address); |
592 add_local_var_and_edge(n, PointsToNode::NoEscape, adr, NULL); |
602 add_local_var_and_edge(n, PointsToNode::NoEscape, adr, NULL); |
593 break; |
603 break; |
594 } |
604 } |
595 ELSE_FAIL("Op_LoadP"); |
605 ELSE_FAIL("Op_LoadP"); |
596 } |
606 } |
597 case Op_Phi: { |
607 case Op_Phi: { |
598 // Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because |
608 // Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because |
599 // ThreadLocal has RawPrt type. |
609 // ThreadLocal has RawPtr type. |
600 const Type* t = n->as_Phi()->type(); |
610 const Type* t = n->as_Phi()->type(); |
601 if (t->make_ptr() != NULL) { |
611 if (t->make_ptr() != NULL) { |
602 for (uint i = 1; i < n->req(); i++) { |
612 for (uint i = 1; i < n->req(); i++) { |
603 Node* in = n->in(i); |
613 Node* in = n->in(i); |
604 if (in == NULL) |
614 if (in == NULL) |
636 } |
646 } |
637 case Op_StoreP: |
647 case Op_StoreP: |
638 case Op_StoreN: |
648 case Op_StoreN: |
639 case Op_StorePConditional: |
649 case Op_StorePConditional: |
640 case Op_CompareAndSwapP: |
650 case Op_CompareAndSwapP: |
641 case Op_CompareAndSwapN: { |
651 case Op_CompareAndSwapN: |
|
652 case Op_GetAndSetP: |
|
653 case Op_GetAndSetN: { |
642 Node* adr = n->in(MemNode::Address); |
654 Node* adr = n->in(MemNode::Address); |
|
655 if (opcode == Op_GetAndSetP || opcode == Op_GetAndSetN) { |
|
656 const Type* t = _igvn->type(n); |
|
657 if (t->make_ptr() != NULL) { |
|
658 add_local_var_and_edge(n, PointsToNode::NoEscape, adr, NULL); |
|
659 } |
|
660 } |
643 const Type *adr_type = _igvn->type(adr); |
661 const Type *adr_type = _igvn->type(adr); |
644 adr_type = adr_type->make_ptr(); |
662 adr_type = adr_type->make_ptr(); |
645 if (adr_type->isa_oopptr() || |
663 if (adr_type->isa_oopptr() || |
646 (opcode == Op_StoreP || opcode == Op_StoreN) && |
664 (opcode == Op_StoreP || opcode == Op_StoreN) && |
647 (adr_type == TypeRawPtr::NOTNULL && |
665 (adr_type == TypeRawPtr::NOTNULL && |