< prev index next >

src/hotspot/share/gc/g1/c1/g1BarrierSetC1.cpp

BarrierSetC1_v3

BarrierSetC1_v2

15  * 2 along with this work; if not, write to the Free Software Foundation,                                                            
16  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.                                                                     
17  *                                                                                                                                   
18  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA                                                           
19  * or visit www.oracle.com if you need additional information or have any                                                            
20  * questions.                                                                                                                        
21  *                                                                                                                                   
22  */                                                                                                                                  
23 
24 #include "precompiled.hpp"                                                                                                           
25 #include "c1/c1_LIRGenerator.hpp"                                                                                                    
26 #include "c1/c1_CodeStubs.hpp"                                                                                                       
27 #include "gc/g1/c1/g1BarrierSetC1.hpp"                                                                                               
28 #include "gc/g1/g1BarrierSet.hpp"                                                                                                    
29 #include "gc/g1/g1BarrierSetAssembler.hpp"                                                                                           
30 #include "gc/g1/g1ThreadLocalData.hpp"                                                                                               
31 #include "gc/g1/heapRegion.hpp"                                                                                                      
32 #include "utilities/macros.hpp"                                                                                                      
33 
34 #ifdef ASSERT                                                                                                                        
35 #define __ lir_generator->lir(__FILE__, __LINE__)->                                                                                  
36 #else                                                                                                                                
37 #define __ lir_generator->lir()->                                                                                                    
38 #endif                                                                                                                               
39 
40 void G1PreBarrierStub::emit_code(LIR_Assembler* ce) {                                                                                
41   G1BarrierSetAssembler* bs = (G1BarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();                            
42   bs->gen_g1_pre_barrier_stub(ce, this);                                                                                             
43 }                                                                                                                                    
44 
45 void G1PostBarrierStub::emit_code(LIR_Assembler* ce) {                                                                               
46   G1BarrierSetAssembler* bs = (G1BarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();                            
47   bs->gen_g1_post_barrier_stub(ce, this);                                                                                            
48 }                                                                                                                                    
49 
50 void G1BarrierSetC1::pre_barrier(LIRGenerator *lir_generator, DecoratorSet decorators,                                               
51                                  LIR_Opr addr_opr, LIR_Opr pre_val, CodeEmitInfo* info) {                                            
                                                                                                                                     
                                                                                                                                     
52   bool in_heap = (decorators & IN_HEAP) != 0;                                                                                        
53   bool in_conc_root = (decorators & IN_CONCURRENT_ROOT) != 0;                                                                        
54   if (!in_heap && !in_conc_root) {                                                                                                   
55     return;                                                                                                                          
56   }                                                                                                                                  
57 
58   // First we test whether marking is in progress.                                                                                   
59   BasicType flag_type;                                                                                                               
60   bool patch = (decorators & C1_NEEDS_PATCHING) != 0;                                                                                
61   bool do_load = pre_val == LIR_OprFact::illegalOpr;                                                                                 
62   if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {                                                                        
63     flag_type = T_INT;                                                                                                               
64   } else {                                                                                                                           
65     guarantee(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1,                                                                  
66               "Assumption");                                                                                                         
67     // Use unsigned type T_BOOLEAN here rather than signed T_BYTE since some platforms, eg. ARM,                                     
68     // need to use unsigned instructions to use the large offset to load the satb_mark_queue.                                        
69     flag_type = T_BOOLEAN;                                                                                                           
70   }                                                                                                                                  
71   LIR_Opr thrd = lir_generator->getThreadPointer();                                                                                  
72   LIR_Address* mark_active_flag_addr =                                                                                               
73     new LIR_Address(thrd,                                                                                                            
74                     in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()),                                                    
75                     flag_type);                                                                                                      
76   // Read the marking-in-progress flag.                                                                                              
77   LIR_Opr flag_val = lir_generator->new_register(T_INT);                                                                             
78   __ load(mark_active_flag_addr, flag_val);                                                                                          
79   __ cmp(lir_cond_notEqual, flag_val, LIR_OprFact::intConst(0));                                                                     
80 
81   LIR_PatchCode pre_val_patch_code = lir_patch_none;                                                                                 
82 
83   CodeStub* slow;                                                                                                                    
84 
85   if (do_load) {                                                                                                                     
86     assert(pre_val == LIR_OprFact::illegalOpr, "sanity");                                                                            
87     assert(addr_opr != LIR_OprFact::illegalOpr, "sanity");                                                                           
88 
89     if (patch)                                                                                                                       
90       pre_val_patch_code = lir_patch_normal;                                                                                         
91 
92     pre_val = lir_generator->new_register(T_OBJECT);                                                                                 
93 
94     if (!addr_opr->is_address()) {                                                                                                   
95       assert(addr_opr->is_register(), "must be");                                                                                    
96       addr_opr = LIR_OprFact::address(new LIR_Address(addr_opr, T_OBJECT));                                                          
97     }                                                                                                                                
98     slow = new G1PreBarrierStub(addr_opr, pre_val, pre_val_patch_code, info);                                                        
99   } else {                                                                                                                           
100     assert(addr_opr == LIR_OprFact::illegalOpr, "sanity");                                                                           
101     assert(pre_val->is_register(), "must be");                                                                                       
102     assert(pre_val->type() == T_OBJECT, "must be an object");                                                                        
103     assert(info == NULL, "sanity");                                                                                                  
104 
105     slow = new G1PreBarrierStub(pre_val);                                                                                            
106   }                                                                                                                                  
107 
108   __ branch(lir_cond_notEqual, T_INT, slow);                                                                                         
109   __ branch_destination(slow->continuation());                                                                                       
110 }                                                                                                                                    
111 
112 void G1BarrierSetC1::post_barrier(LIRGenerator *lir_generator, DecoratorSet decorators,                                              
113                                   LIR_OprDesc* addr, LIR_OprDesc* new_val) {                                                         
                                                                                                                                     
114   bool in_heap = (decorators & IN_HEAP) != 0;                                                                                        
115   if (!in_heap) {                                                                                                                    
116     return;                                                                                                                          
117   }                                                                                                                                  
118 
119   // If the "new_val" is a constant NULL, no barrier is necessary.                                                                   
120   if (new_val->is_constant() &&                                                                                                      
121       new_val->as_constant_ptr()->as_jobject() == NULL) return;                                                                      
122 
123   if (!new_val->is_register()) {                                                                                                     
124     LIR_Opr new_val_reg = lir_generator->new_register(T_OBJECT);                                                                     
125     if (new_val->is_constant()) {                                                                                                    
126       __ move(new_val, new_val_reg);                                                                                                 
127     } else {                                                                                                                         
128       __ leal(new_val, new_val_reg);                                                                                                 
129     }                                                                                                                                
130     new_val = new_val_reg;                                                                                                           
131   }                                                                                                                                  
132   assert(new_val->is_register(), "must be a register at this point");                                                                
133 
134   if (addr->is_address()) {                                                                                                          
135     LIR_Address* address = addr->as_address_ptr();                                                                                   
136     LIR_Opr ptr = lir_generator->new_pointer_register();                                                                             
137     if (!address->index()->is_valid() && address->disp() == 0) {                                                                     
138       __ move(address->base(), ptr);                                                                                                 
139     } else {                                                                                                                         
140       assert(address->disp() != max_jint, "lea doesn't support patched addresses!");                                                 
141       __ leal(addr, ptr);                                                                                                            
142     }                                                                                                                                
143     addr = ptr;                                                                                                                      
144   }                                                                                                                                  
145   assert(addr->is_register(), "must be a register at this point");                                                                   
146 
147   LIR_Opr xor_res = lir_generator->new_pointer_register();                                                                           
148   LIR_Opr xor_shift_res = lir_generator->new_pointer_register();                                                                     
149   if (TwoOperandLIRForm) {                                                                                                           
150     __ move(addr, xor_res);                                                                                                          
151     __ logical_xor(xor_res, new_val, xor_res);                                                                                       
152     __ move(xor_res, xor_shift_res);                                                                                                 
153     __ unsigned_shift_right(xor_shift_res,                                                                                           
154                             LIR_OprFact::intConst(HeapRegion::LogOfHRGrainBytes),                                                    
155                             xor_shift_res,                                                                                           
156                             LIR_OprDesc::illegalOpr());                                                                              
157   } else {                                                                                                                           
158     __ logical_xor(addr, new_val, xor_res);                                                                                          
159     __ unsigned_shift_right(xor_res,                                                                                                 
160                             LIR_OprFact::intConst(HeapRegion::LogOfHRGrainBytes),                                                    
161                             xor_shift_res,                                                                                           
162                             LIR_OprDesc::illegalOpr());                                                                              
163   }                                                                                                                                  
164 
165   if (!new_val->is_register()) {                                                                                                     
166     LIR_Opr new_val_reg = lir_generator->new_register(T_OBJECT);                                                                     
167     __ leal(new_val, new_val_reg);                                                                                                   
168     new_val = new_val_reg;                                                                                                           
169   }                                                                                                                                  
170   assert(new_val->is_register(), "must be a register at this point");                                                                
171 
172   __ cmp(lir_cond_notEqual, xor_shift_res, LIR_OprFact::intptrConst(NULL_WORD));                                                     
173 
174   CodeStub* slow = new G1PostBarrierStub(addr, new_val);                                                                             
175   __ branch(lir_cond_notEqual, LP64_ONLY(T_LONG) NOT_LP64(T_INT), slow);                                                             
176   __ branch_destination(slow->continuation());                                                                                       
177 }                                                                                                                                    
178 
179 void G1BarrierSetC1::load_at_resolved(LIRGenerator *lir_generator, DecoratorSet decorators, BasicType type,                          
180                                       LIR_Opr addr, LIRItem& base, LIR_Opr offset, LIR_Opr result,                                   
181                                       CodeEmitInfo* patch_info, CodeEmitInfo* load_emit_info) {                                      
182   bool is_oop = type == T_OBJECT || type == T_ARRAY;                                                                                 
183   bool is_weak = (decorators & ON_WEAK_OOP_REF) != 0;                                                                                
184   bool is_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0;                                                                          
185   bool is_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;                                                                        
                                                                                                                                     
186 
187   BarrierSetC1::load_at_resolved(lir_generator, decorators, type, addr, base, offset, result, patch_info, load_emit_info);           
188 
189   if (is_oop && (is_weak || is_phantom || is_anonymous)) {                                                                           
190     // Register the value in the referent field with the pre-barrier                                                                 
191     LabelObj *Lcont_anonymous;                                                                                                       
192     if (is_anonymous) {                                                                                                              
193       Lcont_anonymous = new LabelObj();                                                                                              
194       generate_referent_check(lir_generator, base, offset, Lcont_anonymous);                                                         
195     }                                                                                                                                
196     pre_barrier(lir_generator, decorators, LIR_OprFact::illegalOpr /* addr_opr */, result /* pre_val */, patch_info /* info */);     
                                                                                                                                     
197     if (is_anonymous) {                                                                                                              
198       __ branch_destination(Lcont_anonymous->label());                                                                               
199     }                                                                                                                                
200   }                                                                                                                                  
201 }                                                                                                                                    
202 
203 class C1G1PreBarrierCodeGenClosure : public StubAssemblerCodeGenClosure {                                                            
204   virtual OopMapSet* generate_code(StubAssembler* sasm) {                                                                            
205     G1BarrierSetAssembler* bs = (G1BarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();                          
206     bs->generate_c1_pre_barrier_runtime_stub(sasm);                                                                                  
207     return NULL;                                                                                                                     
208   }                                                                                                                                  
209 };                                                                                                                                   
210 
211 class C1G1PostBarrierCodeGenClosure : public StubAssemblerCodeGenClosure {                                                           
212   virtual OopMapSet* generate_code(StubAssembler* sasm) {                                                                            
213     G1BarrierSetAssembler* bs = (G1BarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();                          
214     bs->generate_c1_post_barrier_runtime_stub(sasm);                                                                                 
215     return NULL;                                                                                                                     
216   }                                                                                                                                  
217 };                                                                                                                                   
218 
219 void G1BarrierSetC1::generate_c1_runtime_stubs(BufferBlob* buffer_blob) {                                                            
220   C1G1PreBarrierCodeGenClosure pre_code_gen_cl;                                                                                      
221   C1G1PostBarrierCodeGenClosure post_code_gen_cl;                                                                                    
222   _pre_barrier_c1_runtime_code_blob = Runtime1::generate_blob(buffer_blob, -1, "g1_pre_barrier_slow", false, &pre_code_gen_cl);      
223   _post_barrier_c1_runtime_code_blob = Runtime1::generate_blob(buffer_blob, -1, "g1_post_barrier_slow", false, &post_code_gen_cl);   
                                                                                                                                     
                                                                                                                                     
224 }                                                                                                                                    

15  * 2 along with this work; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17  *
18  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19  * or visit www.oracle.com if you need additional information or have any
20  * questions.
21  *
22  */
23 
24 #include "precompiled.hpp"
25 #include "c1/c1_LIRGenerator.hpp"
26 #include "c1/c1_CodeStubs.hpp"
27 #include "gc/g1/c1/g1BarrierSetC1.hpp"
28 #include "gc/g1/g1BarrierSet.hpp"
29 #include "gc/g1/g1BarrierSetAssembler.hpp"
30 #include "gc/g1/g1ThreadLocalData.hpp"
31 #include "gc/g1/heapRegion.hpp"
32 #include "utilities/macros.hpp"
33 
34 #ifdef ASSERT
35 #define __ gen->lir(__FILE__, __LINE__)->
36 #else
37 #define __ gen->lir()->
38 #endif
39 
40 void G1PreBarrierStub::emit_code(LIR_Assembler* ce) {
41   G1BarrierSetAssembler* bs = (G1BarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();
42   bs->gen_g1_pre_barrier_stub(ce, this);
43 }
44 
45 void G1PostBarrierStub::emit_code(LIR_Assembler* ce) {
46   G1BarrierSetAssembler* bs = (G1BarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();
47   bs->gen_g1_post_barrier_stub(ce, this);
48 }
49 
50 void G1BarrierSetC1::pre_barrier(LIRAccess& access, LIR_Opr addr_opr,
51                                  LIR_Opr pre_val, CodeEmitInfo* info) {
52   LIRGenerator* gen = access.gen();
53   DecoratorSet decorators = access.decorators();
54   bool in_heap = (decorators & IN_HEAP) != 0;
55   bool in_conc_root = (decorators & IN_CONCURRENT_ROOT) != 0;
56   if (!in_heap && !in_conc_root) {
57     return;
58   }
59 
60   // First we test whether marking is in progress.
61   BasicType flag_type;
62   bool patch = (decorators & C1_NEEDS_PATCHING) != 0;
63   bool do_load = pre_val == LIR_OprFact::illegalOpr;
64   if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
65     flag_type = T_INT;
66   } else {
67     guarantee(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1,
68               "Assumption");
69     // Use unsigned type T_BOOLEAN here rather than signed T_BYTE since some platforms, eg. ARM,
70     // need to use unsigned instructions to use the large offset to load the satb_mark_queue.
71     flag_type = T_BOOLEAN;
72   }
73   LIR_Opr thrd = gen->getThreadPointer();
74   LIR_Address* mark_active_flag_addr =
75     new LIR_Address(thrd,
76                     in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()),
77                     flag_type);
78   // Read the marking-in-progress flag.
79   LIR_Opr flag_val = gen->new_register(T_INT);
80   __ load(mark_active_flag_addr, flag_val);
81   __ cmp(lir_cond_notEqual, flag_val, LIR_OprFact::intConst(0));
82 
83   LIR_PatchCode pre_val_patch_code = lir_patch_none;
84 
85   CodeStub* slow;
86 
87   if (do_load) {
88     assert(pre_val == LIR_OprFact::illegalOpr, "sanity");
89     assert(addr_opr != LIR_OprFact::illegalOpr, "sanity");
90 
91     if (patch)
92       pre_val_patch_code = lir_patch_normal;
93 
94     pre_val = gen->new_register(T_OBJECT);
95 
96     if (!addr_opr->is_address()) {
97       assert(addr_opr->is_register(), "must be");
98       addr_opr = LIR_OprFact::address(new LIR_Address(addr_opr, T_OBJECT));
99     }
100     slow = new G1PreBarrierStub(addr_opr, pre_val, pre_val_patch_code, info);
101   } else {
102     assert(addr_opr == LIR_OprFact::illegalOpr, "sanity");
103     assert(pre_val->is_register(), "must be");
104     assert(pre_val->type() == T_OBJECT, "must be an object");
105     assert(info == NULL, "sanity");
106 
107     slow = new G1PreBarrierStub(pre_val);
108   }
109 
110   __ branch(lir_cond_notEqual, T_INT, slow);
111   __ branch_destination(slow->continuation());
112 }
113 
114 void G1BarrierSetC1::post_barrier(LIRAccess& access, LIR_OprDesc* addr, LIR_OprDesc* new_val) {
115   LIRGenerator* gen = access.gen();
116   DecoratorSet decorators = access.decorators();
117   bool in_heap = (decorators & IN_HEAP) != 0;
118   if (!in_heap) {
119     return;
120   }
121 
122   // If the "new_val" is a constant NULL, no barrier is necessary.
123   if (new_val->is_constant() &&
124       new_val->as_constant_ptr()->as_jobject() == NULL) return;
125 
126   if (!new_val->is_register()) {
127     LIR_Opr new_val_reg = gen->new_register(T_OBJECT);
128     if (new_val->is_constant()) {
129       __ move(new_val, new_val_reg);
130     } else {
131       __ leal(new_val, new_val_reg);
132     }
133     new_val = new_val_reg;
134   }
135   assert(new_val->is_register(), "must be a register at this point");
136 
137   if (addr->is_address()) {
138     LIR_Address* address = addr->as_address_ptr();
139     LIR_Opr ptr = gen->new_pointer_register();
140     if (!address->index()->is_valid() && address->disp() == 0) {
141       __ move(address->base(), ptr);
142     } else {
143       assert(address->disp() != max_jint, "lea doesn't support patched addresses!");
144       __ leal(addr, ptr);
145     }
146     addr = ptr;
147   }
148   assert(addr->is_register(), "must be a register at this point");
149 
150   LIR_Opr xor_res = gen->new_pointer_register();
151   LIR_Opr xor_shift_res = gen->new_pointer_register();
152   if (TwoOperandLIRForm) {
153     __ move(addr, xor_res);
154     __ logical_xor(xor_res, new_val, xor_res);
155     __ move(xor_res, xor_shift_res);
156     __ unsigned_shift_right(xor_shift_res,
157                             LIR_OprFact::intConst(HeapRegion::LogOfHRGrainBytes),
158                             xor_shift_res,
159                             LIR_OprDesc::illegalOpr());
160   } else {
161     __ logical_xor(addr, new_val, xor_res);
162     __ unsigned_shift_right(xor_res,
163                             LIR_OprFact::intConst(HeapRegion::LogOfHRGrainBytes),
164                             xor_shift_res,
165                             LIR_OprDesc::illegalOpr());
166   }
167 
168   if (!new_val->is_register()) {
169     LIR_Opr new_val_reg = gen->new_register(T_OBJECT);
170     __ leal(new_val, new_val_reg);
171     new_val = new_val_reg;
172   }
173   assert(new_val->is_register(), "must be a register at this point");
174 
175   __ cmp(lir_cond_notEqual, xor_shift_res, LIR_OprFact::intptrConst(NULL_WORD));
176 
177   CodeStub* slow = new G1PostBarrierStub(addr, new_val);
178   __ branch(lir_cond_notEqual, LP64_ONLY(T_LONG) NOT_LP64(T_INT), slow);
179   __ branch_destination(slow->continuation());
180 }
181 
182 void G1BarrierSetC1::load_at_resolved(LIRAccess& access, LIR_Opr result) {
183   DecoratorSet decorators = access.decorators();


184   bool is_weak = (decorators & ON_WEAK_OOP_REF) != 0;
185   bool is_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0;
186   bool is_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
187   LIRGenerator *gen = access.gen();
188 
189   BarrierSetC1::load_at_resolved(access, result);
190 
191   if (access.is_oop() && (is_weak || is_phantom || is_anonymous)) {
192     // Register the value in the referent field with the pre-barrier
193     LabelObj *Lcont_anonymous;
194     if (is_anonymous) {
195       Lcont_anonymous = new LabelObj();
196       generate_referent_check(access, Lcont_anonymous);
197     }
198     pre_barrier(access, LIR_OprFact::illegalOpr /* addr_opr */,
199                 result /* pre_val */, access.patch_info() /* info */);
200     if (is_anonymous) {
201       __ branch_destination(Lcont_anonymous->label());
202     }
203   }
204 }
205 
206 class C1G1PreBarrierCodeGenClosure : public StubAssemblerCodeGenClosure {
207   virtual OopMapSet* generate_code(StubAssembler* sasm) {
208     G1BarrierSetAssembler* bs = (G1BarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();
209     bs->generate_c1_pre_barrier_runtime_stub(sasm);
210     return NULL;
211   }
212 };
213 
214 class C1G1PostBarrierCodeGenClosure : public StubAssemblerCodeGenClosure {
215   virtual OopMapSet* generate_code(StubAssembler* sasm) {
216     G1BarrierSetAssembler* bs = (G1BarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();
217     bs->generate_c1_post_barrier_runtime_stub(sasm);
218     return NULL;
219   }
220 };
221 
222 void G1BarrierSetC1::generate_c1_runtime_stubs(BufferBlob* buffer_blob) {
223   C1G1PreBarrierCodeGenClosure pre_code_gen_cl;
224   C1G1PostBarrierCodeGenClosure post_code_gen_cl;
225   _pre_barrier_c1_runtime_code_blob = Runtime1::generate_blob(buffer_blob, -1, "g1_pre_barrier_slow",
226                                                               false, &pre_code_gen_cl);
227   _post_barrier_c1_runtime_code_blob = Runtime1::generate_blob(buffer_blob, -1, "g1_post_barrier_slow",
228                                                                false, &post_code_gen_cl);
229 }
< prev index next >