< prev index next >

src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp

Print this page

137   __ cbz(pre_val, done);
138 
139   // Can we store original value in the thread's buffer?
140   // Is index == 0?
141   // (The index field is typed as size_t.)
142 
143   __ ldr(tmp, index);                      // tmp := *index_adr
144   __ cbz(tmp, runtime);                    // tmp == 0?
145                                         // If yes, goto runtime
146 
147   __ sub(tmp, tmp, wordSize);              // tmp := tmp - wordSize
148   __ str(tmp, index);                      // *index_adr := tmp
149   __ ldr(rscratch1, buffer);
150   __ add(tmp, tmp, rscratch1);             // tmp := tmp + *buffer_adr
151 
152   // Record the previous value
153   __ str(pre_val, Address(tmp, 0));
154   __ b(done);
155 
156   __ bind(runtime);
157   // save the live input values
158   RegSet saved = RegSet::of(pre_val);
159   if (tosca_live) saved += RegSet::of(r0);
160   if (obj != noreg) saved += RegSet::of(obj);
161 
162   __ push(saved, sp);
163 
164   // Calling the runtime using the regular call_VM_leaf mechanism generates
165   // code (generated by InterpreterMacroAssember::call_VM_leaf_base)
166   // that checks that the *(rfp+frame::interpreter_frame_last_sp) == NULL.
167   //
168   // If we care generating the pre-barrier without a frame (e.g. in the
169   // intrinsified Reference.get() routine) then ebp might be pointing to
170   // the caller frame and so this check will most likely fail at runtime.
171   //
172   // Expanding the call directly bypasses the generation of the check.
173   // So when we do not have have a full interpreter frame on the stack
174   // expand_call should be passed true.
175 
176   if (expand_call) {
177     assert(pre_val != c_rarg1, "smashed arg");
178     __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), pre_val, thread);
179   } else {
180     __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), pre_val, thread);
181   }
182 
183   __ pop(saved, sp);
184 
185   __ bind(done);
186 
187 }
188 
189 void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm,
190                                                   Register store_addr,
191                                                   Register new_val,
192                                                   Register thread,
193                                                   Register tmp,
194                                                   Register tmp2) {
195   assert(thread == rthread, "must be");
196   assert_different_registers(store_addr, new_val, thread, tmp, tmp2,
197                              rscratch1);
198   assert(store_addr != noreg && new_val != noreg && tmp != noreg
199          && tmp2 != noreg, "expecting a register");
200 
201   Address queue_index(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset()));
202   Address buffer(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset()));
203 

137   __ cbz(pre_val, done);
138 
139   // Can we store original value in the thread's buffer?
140   // Is index == 0?
141   // (The index field is typed as size_t.)
142 
143   __ ldr(tmp, index);                      // tmp := *index_adr
144   __ cbz(tmp, runtime);                    // tmp == 0?
145                                         // If yes, goto runtime
146 
147   __ sub(tmp, tmp, wordSize);              // tmp := tmp - wordSize
148   __ str(tmp, index);                      // *index_adr := tmp
149   __ ldr(rscratch1, buffer);
150   __ add(tmp, tmp, rscratch1);             // tmp := tmp + *buffer_adr
151 
152   // Record the previous value
153   __ str(pre_val, Address(tmp, 0));
154   __ b(done);
155 
156   __ bind(runtime);




157 
158   __ push_call_clobbered_registers();
159 
160   // Calling the runtime using the regular call_VM_leaf mechanism generates
161   // code (generated by InterpreterMacroAssember::call_VM_leaf_base)
162   // that checks that the *(rfp+frame::interpreter_frame_last_sp) == NULL.
163   //
164   // If we care generating the pre-barrier without a frame (e.g. in the
165   // intrinsified Reference.get() routine) then ebp might be pointing to
166   // the caller frame and so this check will most likely fail at runtime.
167   //
168   // Expanding the call directly bypasses the generation of the check.
169   // So when we do not have have a full interpreter frame on the stack
170   // expand_call should be passed true.
171 
172   if (expand_call) {
173     assert(pre_val != c_rarg1, "smashed arg");
174     __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), pre_val, thread);
175   } else {
176     __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), pre_val, thread);
177   }
178 
179   __ pop_call_clobbered_registers();
180 
181   __ bind(done);
182 
183 }
184 
185 void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm,
186                                                   Register store_addr,
187                                                   Register new_val,
188                                                   Register thread,
189                                                   Register tmp,
190                                                   Register tmp2) {
191   assert(thread == rthread, "must be");
192   assert_different_registers(store_addr, new_val, thread, tmp, tmp2,
193                              rscratch1);
194   assert(store_addr != noreg && new_val != noreg && tmp != noreg
195          && tmp2 != noreg, "expecting a register");
196 
197   Address queue_index(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset()));
198   Address buffer(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset()));
199 
< prev index next >