Mercurial > hg > truffle
comparison src/share/vm/opto/memnode.cpp @ 1100:f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
Summary: Add missing checks for MemBar nodes in EA.
Reviewed-by: never
author | kvn |
---|---|
date | Wed, 09 Dec 2009 16:40:45 -0800 |
parents | 7c57aead6d3e |
children | c18cbe5936b8 |
comparison
equal
deleted
inserted
replaced
1099:c5d3d979ae27 | 1100:f96a1a986f7b |
---|---|
121 } else if (proj_in->is_MemBar()) { | 121 } else if (proj_in->is_MemBar()) { |
122 result = proj_in->in(TypeFunc::Memory); | 122 result = proj_in->in(TypeFunc::Memory); |
123 } else { | 123 } else { |
124 assert(false, "unexpected projection"); | 124 assert(false, "unexpected projection"); |
125 } | 125 } |
126 } else if (result->is_ClearArray()) { | |
127 if (!ClearArrayNode::step_through(&result, instance_id, phase)) { | |
128 // Can not bypass initialization of the instance | |
129 // we are looking for. | |
130 break; | |
131 } | |
132 // Otherwise skip it (the call updated 'result' value). | |
126 } else if (result->is_MergeMem()) { | 133 } else if (result->is_MergeMem()) { |
127 result = step_through_mergemem(phase, result->as_MergeMem(), t_adr, NULL, tty); | 134 result = step_through_mergemem(phase, result->as_MergeMem(), t_adr, NULL, tty); |
128 } | 135 } |
129 } | 136 } |
130 return result; | 137 return result; |
535 continue; // (a) advance through independent call memory | 542 continue; // (a) advance through independent call memory |
536 } | 543 } |
537 } else if (mem->is_Proj() && mem->in(0)->is_MemBar()) { | 544 } else if (mem->is_Proj() && mem->in(0)->is_MemBar()) { |
538 mem = mem->in(0)->in(TypeFunc::Memory); | 545 mem = mem->in(0)->in(TypeFunc::Memory); |
539 continue; // (a) advance through independent MemBar memory | 546 continue; // (a) advance through independent MemBar memory |
547 } else if (mem->is_ClearArray()) { | |
548 if (ClearArrayNode::step_through(&mem, (uint)addr_t->instance_id(), phase)) { | |
549 // (the call updated 'mem' value) | |
550 continue; // (a) advance through independent allocation memory | |
551 } else { | |
552 // Can not bypass initialization of the instance | |
553 // we are looking for. | |
554 return mem; | |
555 } | |
540 } else if (mem->is_MergeMem()) { | 556 } else if (mem->is_MergeMem()) { |
541 int alias_idx = phase->C->get_alias_index(adr_type()); | 557 int alias_idx = phase->C->get_alias_index(adr_type()); |
542 mem = mem->as_MergeMem()->memory_at(alias_idx); | 558 mem = mem->as_MergeMem()->memory_at(alias_idx); |
543 continue; // (a) advance through independent MergeMem memory | 559 continue; // (a) advance through independent MergeMem memory |
544 } | 560 } |
2452 mem = new (phase->C, 4) StoreLNode(in(0),mem,adr,atp,zero); | 2468 mem = new (phase->C, 4) StoreLNode(in(0),mem,adr,atp,zero); |
2453 } | 2469 } |
2454 return mem; | 2470 return mem; |
2455 } | 2471 } |
2456 | 2472 |
2473 //----------------------------step_through---------------------------------- | |
2474 // Return allocation input memory edge if it is different instance | |
2475 // or itself if it is the one we are looking for. | |
2476 bool ClearArrayNode::step_through(Node** np, uint instance_id, PhaseTransform* phase) { | |
2477 Node* n = *np; | |
2478 assert(n->is_ClearArray(), "sanity"); | |
2479 intptr_t offset; | |
2480 AllocateNode* alloc = AllocateNode::Ideal_allocation(n->in(3), phase, offset); | |
2481 // This method is called only before Allocate nodes are expanded during | |
2482 // macro nodes expansion. Before that ClearArray nodes are only generated | |
2483 // in LibraryCallKit::generate_arraycopy() which follows allocations. | |
2484 assert(alloc != NULL, "should have allocation"); | |
2485 if (alloc->_idx == instance_id) { | |
2486 // Can not bypass initialization of the instance we are looking for. | |
2487 return false; | |
2488 } | |
2489 // Otherwise skip it. | |
2490 InitializeNode* init = alloc->initialization(); | |
2491 if (init != NULL) | |
2492 *np = init->in(TypeFunc::Memory); | |
2493 else | |
2494 *np = alloc->in(TypeFunc::Memory); | |
2495 return true; | |
2496 } | |
2497 | |
2457 //----------------------------clear_memory------------------------------------- | 2498 //----------------------------clear_memory------------------------------------- |
2458 // Generate code to initialize object storage to zero. | 2499 // Generate code to initialize object storage to zero. |
2459 Node* ClearArrayNode::clear_memory(Node* ctl, Node* mem, Node* dest, | 2500 Node* ClearArrayNode::clear_memory(Node* ctl, Node* mem, Node* dest, |
2460 intptr_t start_offset, | 2501 intptr_t start_offset, |
2461 Node* end_offset, | 2502 Node* end_offset, |
2625 | 2666 |
2626 //------------------------------Ideal------------------------------------------ | 2667 //------------------------------Ideal------------------------------------------ |
2627 // Return a node which is more "ideal" than the current node. Strip out | 2668 // Return a node which is more "ideal" than the current node. Strip out |
2628 // control copies | 2669 // control copies |
2629 Node *MemBarNode::Ideal(PhaseGVN *phase, bool can_reshape) { | 2670 Node *MemBarNode::Ideal(PhaseGVN *phase, bool can_reshape) { |
2630 return remove_dead_region(phase, can_reshape) ? this : NULL; | 2671 if (remove_dead_region(phase, can_reshape)) return this; |
2672 | |
2673 // Eliminate volatile MemBars for scalar replaced objects. | |
2674 if (can_reshape && req() == (Precedent+1) && | |
2675 (Opcode() == Op_MemBarAcquire || Opcode() == Op_MemBarVolatile)) { | |
2676 // Volatile field loads and stores. | |
2677 Node* my_mem = in(MemBarNode::Precedent); | |
2678 if (my_mem != NULL && my_mem->is_Mem()) { | |
2679 const TypeOopPtr* t_oop = my_mem->in(MemNode::Address)->bottom_type()->isa_oopptr(); | |
2680 // Check for scalar replaced object reference. | |
2681 if( t_oop != NULL && t_oop->is_known_instance_field() && | |
2682 t_oop->offset() != Type::OffsetBot && | |
2683 t_oop->offset() != Type::OffsetTop) { | |
2684 // Replace MemBar projections by its inputs. | |
2685 PhaseIterGVN* igvn = phase->is_IterGVN(); | |
2686 igvn->replace_node(proj_out(TypeFunc::Memory), in(TypeFunc::Memory)); | |
2687 igvn->replace_node(proj_out(TypeFunc::Control), in(TypeFunc::Control)); | |
2688 // Must return either the original node (now dead) or a new node | |
2689 // (Do not return a top here, since that would break the uniqueness of top.) | |
2690 return new (phase->C, 1) ConINode(TypeInt::ZERO); | |
2691 } | |
2692 } | |
2693 } | |
2694 return NULL; | |
2631 } | 2695 } |
2632 | 2696 |
2633 //------------------------------Value------------------------------------------ | 2697 //------------------------------Value------------------------------------------ |
2634 const Type *MemBarNode::Value( PhaseTransform *phase ) const { | 2698 const Type *MemBarNode::Value( PhaseTransform *phase ) const { |
2635 if( !in(0) ) return Type::TOP; | 2699 if( !in(0) ) return Type::TOP; |