< prev index next >

src/hotspot/share/gc/shared/barrierSetNMethod.cpp

Print this page

166 }
167 
168 int BarrierSetNMethod::nmethod_stub_entry_barrier(address* return_address_ptr) {
169   // Enable WXWrite: the function is called directly from nmethod_entry_barrier
170   // stub.
171   MACOS_AARCH64_ONLY(ThreadWXEnable wx(WXWrite, Thread::current()));
172 
173   address return_address = *return_address_ptr;
174   AARCH64_PORT_ONLY(return_address = pauth_strip_pointer(return_address));
175   CodeBlob* cb = CodeCache::find_blob(return_address);
176   assert(cb != nullptr, "invariant");
177 
178   nmethod* nm = cb->as_nmethod();
179   BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod();
180 
181   if (!bs_nm->is_armed(nm)) {
182     return 0;
183   }
184 
185   assert(!nm->is_osr_method(), "Should not reach here");

186   // Called upon first entry after being armed
187   bool may_enter = bs_nm->nmethod_entry_barrier(nm);
188 
189   // In case a concurrent thread disarmed the nmethod, we need to ensure the new instructions
190   // are made visible, by using a cross modify fence. Note that this is synchronous cross modifying
191   // code, where the existence of new instructions is communicated via data (the guard value).
192   // This cross modify fence is only needed when the nmethod entry barrier modifies the
193   // instructions. Not all platforms currently do that, so if this check becomes expensive,
194   // it can be made conditional on the nmethod_patching_type.
195   OrderAccess::cross_modify_fence();
196 
197   // Diagnostic option to force deoptimization 1 in 3 times. It is otherwise
198   // a very rare event.
199   if (DeoptimizeNMethodBarriersALot) {
200     static volatile uint32_t counter=0;
201     if (Atomic::add(&counter, 1u) % 3 == 0) {
202       may_enter = false;
203     }
204   }
205 
206   if (!may_enter) {


207     log_trace(nmethod, barrier)("Deoptimizing nmethod: " PTR_FORMAT, p2i(nm));
208     bs_nm->deoptimize(nm, return_address_ptr);
209   }
210   return may_enter ? 0 : 1;
211 }
212 
213 bool BarrierSetNMethod::nmethod_osr_entry_barrier(nmethod* nm) {
214   // This check depends on the invariant that all nmethods that are deoptimized / made not entrant
215   // are NOT disarmed.
216   // This invariant is important because a method can be deoptimized after the method have been
217   // resolved / looked up by OSR by another thread. By not deoptimizing them we guarantee that
218   // a deoptimized method will always hit the barrier and come to the same conclusion - deoptimize
219   if (!is_armed(nm)) {
220     return true;
221   }
222 
223   assert(nm->is_osr_method(), "Should not reach here");
224   log_trace(nmethod, barrier)("Running osr nmethod entry barrier: " PTR_FORMAT, p2i(nm));
225   bool result = nmethod_entry_barrier(nm);



226   OrderAccess::cross_modify_fence();
227   return result;
228 }

166 }
167 
168 int BarrierSetNMethod::nmethod_stub_entry_barrier(address* return_address_ptr) {
169   // Enable WXWrite: the function is called directly from nmethod_entry_barrier
170   // stub.
171   MACOS_AARCH64_ONLY(ThreadWXEnable wx(WXWrite, Thread::current()));
172 
173   address return_address = *return_address_ptr;
174   AARCH64_PORT_ONLY(return_address = pauth_strip_pointer(return_address));
175   CodeBlob* cb = CodeCache::find_blob(return_address);
176   assert(cb != nullptr, "invariant");
177 
178   nmethod* nm = cb->as_nmethod();
179   BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod();
180 
181   if (!bs_nm->is_armed(nm)) {
182     return 0;
183   }
184 
185   assert(!nm->is_osr_method(), "Should not reach here");
186   log_trace(nmethod, barrier)("Running nmethod entry barrier: %d " PTR_FORMAT, nm->compile_id(), p2i(nm));
187   // Called upon first entry after being armed
188   bool may_enter = bs_nm->nmethod_entry_barrier(nm);
189 
190   // In case a concurrent thread disarmed the nmethod, we need to ensure the new instructions
191   // are made visible, by using a cross modify fence. Note that this is synchronous cross modifying
192   // code, where the existence of new instructions is communicated via data (the guard value).
193   // This cross modify fence is only needed when the nmethod entry barrier modifies the
194   // instructions. Not all platforms currently do that, so if this check becomes expensive,
195   // it can be made conditional on the nmethod_patching_type.
196   OrderAccess::cross_modify_fence();
197 
198   // Diagnostic option to force deoptimization 1 in 3 times. It is otherwise
199   // a very rare event.
200   if (DeoptimizeNMethodBarriersALot) {
201     static volatile uint32_t counter=0;
202     if (Atomic::add(&counter, 1u) % 3 == 0) {
203       may_enter = false;
204     }
205   }
206 
207   if (may_enter) {
208     nm->set_used();
209   } else {
210     log_trace(nmethod, barrier)("Deoptimizing nmethod: " PTR_FORMAT, p2i(nm));
211     bs_nm->deoptimize(nm, return_address_ptr);
212   }
213   return may_enter ? 0 : 1;
214 }
215 
216 bool BarrierSetNMethod::nmethod_osr_entry_barrier(nmethod* nm) {
217   // This check depends on the invariant that all nmethods that are deoptimized / made not entrant
218   // are NOT disarmed.
219   // This invariant is important because a method can be deoptimized after the method have been
220   // resolved / looked up by OSR by another thread. By not deoptimizing them we guarantee that
221   // a deoptimized method will always hit the barrier and come to the same conclusion - deoptimize
222   if (!is_armed(nm)) {
223     return true;
224   }
225 
226   assert(nm->is_osr_method(), "Should not reach here");
227   log_trace(nmethod, barrier)("Running osr nmethod entry barrier: %d " PTR_FORMAT, nm->compile_id(), p2i(nm));
228   bool result = nmethod_entry_barrier(nm);
229   if (result) {
230     nm->set_used();
231   }
232   OrderAccess::cross_modify_fence();
233   return result;
234 }
< prev index next >