Mon, 14 Sep 2009 09:49:54 -0700
6877254: Server vm crashes with no branches off of store slice" when run with CMS and UseSuperWord(default)
Summary: design StoreCMNode::Ideal to promote its oopStore input if the input is a MergeMem node
Reviewed-by: kvn, never
1.1 --- a/src/share/vm/opto/graphKit.cpp Thu Sep 10 18:18:06 2009 -0700 1.2 +++ b/src/share/vm/opto/graphKit.cpp Mon Sep 14 09:49:54 2009 -0700 1.3 @@ -1450,7 +1450,7 @@ 1.4 1.5 case BarrierSet::CardTableModRef: 1.6 case BarrierSet::CardTableExtension: 1.7 - write_barrier_post(store, obj, adr, val, use_precise); 1.8 + write_barrier_post(store, obj, adr, adr_idx, val, use_precise); 1.9 break; 1.10 1.11 case BarrierSet::ModRef: 1.12 @@ -3165,6 +3165,7 @@ 1.13 void GraphKit::write_barrier_post(Node* oop_store, 1.14 Node* obj, 1.15 Node* adr, 1.16 + uint adr_idx, 1.17 Node* val, 1.18 bool use_precise) { 1.19 // No store check needed if we're storing a NULL or an old object 1.20 @@ -3214,7 +3215,7 @@ 1.21 __ store(__ ctrl(), card_adr, zero, bt, adr_type); 1.22 } else { 1.23 // Specialized path for CM store barrier 1.24 - __ storeCM(__ ctrl(), card_adr, zero, oop_store, bt, adr_type); 1.25 + __ storeCM(__ ctrl(), card_adr, zero, oop_store, adr_idx, bt, adr_type); 1.26 } 1.27 1.28 // Final sync IdealKit and GraphKit. 1.29 @@ -3314,6 +3315,7 @@ 1.30 void GraphKit::g1_mark_card(IdealKit& ideal, 1.31 Node* card_adr, 1.32 Node* oop_store, 1.33 + uint oop_alias_idx, 1.34 Node* index, 1.35 Node* index_adr, 1.36 Node* buffer, 1.37 @@ -3323,7 +3325,7 @@ 1.38 Node* no_base = __ top(); 1.39 BasicType card_bt = T_BYTE; 1.40 // Smash zero into card. MUST BE ORDERED WRT TO STORE 1.41 - __ storeCM(__ ctrl(), card_adr, zero, oop_store, card_bt, Compile::AliasIdxRaw); 1.42 + __ storeCM(__ ctrl(), card_adr, zero, oop_store, oop_alias_idx, card_bt, Compile::AliasIdxRaw); 1.43 1.44 // Now do the queue work 1.45 __ if_then(index, BoolTest::ne, zero); { 1.46 @@ -3435,13 +3437,13 @@ 1.47 Node* card_val = __ load(__ ctrl(), card_adr, TypeInt::INT, T_BYTE, Compile::AliasIdxRaw); 1.48 1.49 __ if_then(card_val, BoolTest::ne, zero); { 1.50 - g1_mark_card(ideal, card_adr, oop_store, index, index_adr, buffer, tf); 1.51 + g1_mark_card(ideal, card_adr, oop_store, alias_idx, index, index_adr, buffer, tf); 1.52 } __ end_if(); 1.53 } __ end_if(); 1.54 } __ end_if(); 1.55 } else { 1.56 // Object.clone() instrinsic uses this path. 1.57 - g1_mark_card(ideal, card_adr, oop_store, index, index_adr, buffer, tf); 1.58 + g1_mark_card(ideal, card_adr, oop_store, alias_idx, index, index_adr, buffer, tf); 1.59 } 1.60 1.61 // Final sync IdealKit and GraphKit.
2.1 --- a/src/share/vm/opto/graphKit.hpp Thu Sep 10 18:18:06 2009 -0700 2.2 +++ b/src/share/vm/opto/graphKit.hpp Mon Sep 14 09:49:54 2009 -0700 2.3 @@ -603,7 +603,8 @@ 2.4 void sync_kit(IdealKit& ideal); 2.5 2.6 // vanilla/CMS post barrier 2.7 - void write_barrier_post(Node *store, Node* obj, Node* adr, Node* val, bool use_precise); 2.8 + void write_barrier_post(Node *store, Node* obj, 2.9 + Node* adr, uint adr_idx, Node* val, bool use_precise); 2.10 2.11 // G1 pre/post barriers 2.12 void g1_write_barrier_pre(Node* obj, 2.13 @@ -622,7 +623,8 @@ 2.14 bool use_precise); 2.15 // Helper function for g1 2.16 private: 2.17 - void g1_mark_card(IdealKit& ideal, Node* card_adr, Node* store, Node* index, Node* index_adr, 2.18 + void g1_mark_card(IdealKit& ideal, Node* card_adr, Node* store, uint oop_alias_idx, 2.19 + Node* index, Node* index_adr, 2.20 Node* buffer, const TypeFunc* tf); 2.21 2.22 public:
3.1 --- a/src/share/vm/opto/idealKit.cpp Thu Sep 10 18:18:06 2009 -0700 3.2 +++ b/src/share/vm/opto/idealKit.cpp Mon Sep 14 09:49:54 2009 -0700 3.3 @@ -378,7 +378,7 @@ 3.4 3.5 // Card mark store. Must be ordered so that it will come after the store of 3.6 // the oop. 3.7 -Node* IdealKit::storeCM(Node* ctl, Node* adr, Node *val, Node* oop_store, 3.8 +Node* IdealKit::storeCM(Node* ctl, Node* adr, Node *val, Node* oop_store, int oop_adr_idx, 3.9 BasicType bt, 3.10 int adr_idx) { 3.11 assert(adr_idx != Compile::AliasIdxTop, "use other store_to_memory factory" ); 3.12 @@ -388,7 +388,7 @@ 3.13 3.14 // Add required edge to oop_store, optimizer does not support precedence edges. 3.15 // Convert required edge to precedence edge before allocation. 3.16 - Node* st = new (C, 5) StoreCMNode(ctl, mem, adr, adr_type, val, oop_store); 3.17 + Node* st = new (C, 5) StoreCMNode(ctl, mem, adr, adr_type, val, oop_store, oop_adr_idx); 3.18 3.19 st = transform(st); 3.20 set_memory(st, adr_idx);
4.1 --- a/src/share/vm/opto/idealKit.hpp Thu Sep 10 18:18:06 2009 -0700 4.2 +++ b/src/share/vm/opto/idealKit.hpp Mon Sep 14 09:49:54 2009 -0700 4.3 @@ -216,6 +216,7 @@ 4.4 Node* adr, 4.5 Node* val, 4.6 Node* oop_store, 4.7 + int oop_adr_idx, 4.8 BasicType bt, 4.9 int adr_idx); 4.10
5.1 --- a/src/share/vm/opto/memnode.cpp Thu Sep 10 18:18:06 2009 -0700 5.2 +++ b/src/share/vm/opto/memnode.cpp Mon Sep 14 09:49:54 2009 -0700 5.3 @@ -2313,6 +2313,22 @@ 5.4 return this; 5.5 } 5.6 5.7 +//============================================================================= 5.8 +//------------------------------Ideal--------------------------------------- 5.9 +Node *StoreCMNode::Ideal(PhaseGVN *phase, bool can_reshape){ 5.10 + Node* progress = StoreNode::Ideal(phase, can_reshape); 5.11 + if (progress != NULL) return progress; 5.12 + 5.13 + Node* my_store = in(MemNode::OopStore); 5.14 + if (my_store->is_MergeMem()) { 5.15 + Node* mem = my_store->as_MergeMem()->memory_at(oop_alias_idx()); 5.16 + set_req(MemNode::OopStore, mem); 5.17 + return this; 5.18 + } 5.19 + 5.20 + return NULL; 5.21 +} 5.22 + 5.23 //------------------------------Value----------------------------------------- 5.24 const Type *StoreCMNode::Value( PhaseTransform *phase ) const { 5.25 // Either input is TOP ==> the result is TOP
6.1 --- a/src/share/vm/opto/memnode.hpp Thu Sep 10 18:18:06 2009 -0700 6.2 +++ b/src/share/vm/opto/memnode.hpp Mon Sep 14 09:49:54 2009 -0700 6.3 @@ -582,12 +582,16 @@ 6.4 // The last StoreCM before a SafePoint must be preserved and occur after its "oop" store 6.5 // Preceeding equivalent StoreCMs may be eliminated. 6.6 class StoreCMNode : public StoreNode { 6.7 + private: 6.8 + int _oop_alias_idx; // The alias_idx of OopStore 6.9 public: 6.10 - StoreCMNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, Node *oop_store ) : StoreNode(c,mem,adr,at,val,oop_store) {} 6.11 + StoreCMNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, Node *oop_store, int oop_alias_idx ) : StoreNode(c,mem,adr,at,val,oop_store), _oop_alias_idx(oop_alias_idx) {} 6.12 virtual int Opcode() const; 6.13 virtual Node *Identity( PhaseTransform *phase ); 6.14 + virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 6.15 virtual const Type *Value( PhaseTransform *phase ) const; 6.16 virtual BasicType memory_type() const { return T_VOID; } // unspecific 6.17 + int oop_alias_idx() const { return _oop_alias_idx; } 6.18 }; 6.19 6.20 //------------------------------LoadPLockedNode---------------------------------
7.1 --- a/src/share/vm/opto/superword.cpp Thu Sep 10 18:18:06 2009 -0700 7.2 +++ b/src/share/vm/opto/superword.cpp Mon Sep 14 09:49:54 2009 -0700 7.3 @@ -457,10 +457,6 @@ 7.4 } else if (out->Opcode() == Op_StoreCM && out->in(MemNode::OopStore) == n) { 7.5 // StoreCM has an input edge used as a precedence edge. 7.6 // Maybe an issue when oop stores are vectorized. 7.7 - } else if( out->is_MergeMem() && prev && 7.8 - prev->Opcode() == Op_StoreCM && out == prev->in(MemNode::OopStore)) { 7.9 - // Oop store is a MergeMem! This should not happen. Temporarily remove the assertion 7.10 - // for this case because it could not be superwordized anyway. 7.11 } else { 7.12 assert(out == prev || prev == NULL, "no branches off of store slice"); 7.13 }
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/test/compiler/6877254/Test.java Mon Sep 14 09:49:54 2009 -0700 8.3 @@ -0,0 +1,51 @@ 8.4 +/* 8.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. 8.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 8.7 + * 8.8 + * This code is free software; you can redistribute it and/or modify it 8.9 + * under the terms of the GNU General Public License version 2 only, as 8.10 + * published by the Free Software Foundation. 8.11 + * 8.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 8.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 8.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 8.15 + * version 2 for more details (a copy is included in the LICENSE file that 8.16 + * accompanied this code). 8.17 + * 8.18 + * You should have received a copy of the GNU General Public License version 8.19 + * 2 along with this work; if not, write to the Free Software Foundation, 8.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 8.21 + * 8.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 8.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 8.24 + * have any questions. 8.25 + */ 8.26 + 8.27 +/** 8.28 + * @test 8.29 + * @bug 6877254 8.30 + * @summary Implement StoreCMNode::Ideal to promote its OopStore above the MergeMem 8.31 + * 8.32 + * @run main/othervm -server -Xcomp -XX:+UseConcMarkSweepGC Test 8.33 + */ 8.34 + 8.35 +public class Test { 8.36 + static byte var_1; 8.37 + static String var_2 = ""; 8.38 + static byte var_3; 8.39 + static float var_4 = 0; 8.40 + 8.41 + public static void main(String[] args) { 8.42 + int i = 0; 8.43 + 8.44 + for (String var_tmp = var_2; i < 11; var_1 = 0, i++) { 8.45 + var_2 = var_2; 8.46 + var_4 *= (var_4 *= (var_3 = 0)); 8.47 + } 8.48 + 8.49 + System.out.println("var_1 = " + var_1); 8.50 + System.out.println("var_2 = " + var_2); 8.51 + System.out.println("var_3 = " + var_3); 8.52 + System.out.println("var_4 = " + var_4); 8.53 + } 8.54 +}