142 |
142 |
143 thread->set_cached_monitor_info(info); |
143 thread->set_cached_monitor_info(info); |
144 return info; |
144 return info; |
145 } |
145 } |
146 |
146 |
147 |
|
148 static BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_bulk, JavaThread* requesting_thread) { |
147 static BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_bulk, JavaThread* requesting_thread) { |
149 markOop mark = obj->mark(); |
148 markOop mark = obj->mark(); |
150 if (!mark->has_bias_pattern()) { |
149 if (!mark->has_bias_pattern()) { |
151 if (TraceBiasedLocking) { |
150 if (log_is_enabled(Info, biasedlocking)) { |
152 ResourceMark rm; |
151 ResourceMark rm; |
153 tty->print_cr(" (Skipping revocation of object of type %s because it's no longer biased)", |
152 log_info(biasedlocking)(" (Skipping revocation of object of type %s " |
154 obj->klass()->external_name()); |
153 "because it's no longer biased)", |
|
154 obj->klass()->external_name()); |
155 } |
155 } |
156 return BiasedLocking::NOT_BIASED; |
156 return BiasedLocking::NOT_BIASED; |
157 } |
157 } |
158 |
158 |
159 uint age = mark->age(); |
159 uint age = mark->age(); |
160 markOop biased_prototype = markOopDesc::biased_locking_prototype()->set_age(age); |
160 markOop biased_prototype = markOopDesc::biased_locking_prototype()->set_age(age); |
161 markOop unbiased_prototype = markOopDesc::prototype()->set_age(age); |
161 markOop unbiased_prototype = markOopDesc::prototype()->set_age(age); |
162 |
162 |
163 if (TraceBiasedLocking && (Verbose || !is_bulk)) { |
163 // Log at "info" level if not bulk, else "trace" level |
|
164 if (!is_bulk) { |
164 ResourceMark rm; |
165 ResourceMark rm; |
165 tty->print_cr("Revoking bias of object " INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s , prototype header " INTPTR_FORMAT " , allow rebias %d , requesting thread " INTPTR_FORMAT, |
166 log_info(biasedlocking)("Revoking bias of object " INTPTR_FORMAT " , mark " |
166 p2i((void *)obj), (intptr_t) mark, obj->klass()->external_name(), (intptr_t) obj->klass()->prototype_header(), (allow_rebias ? 1 : 0), (intptr_t) requesting_thread); |
167 INTPTR_FORMAT " , type %s , prototype header " INTPTR_FORMAT |
|
168 " , allow rebias %d , requesting thread " INTPTR_FORMAT, |
|
169 p2i((void *)obj), |
|
170 (intptr_t) mark, |
|
171 obj->klass()->external_name(), |
|
172 (intptr_t) obj->klass()->prototype_header(), |
|
173 (allow_rebias ? 1 : 0), |
|
174 (intptr_t) requesting_thread); |
|
175 } else { |
|
176 ResourceMark rm; |
|
177 log_trace(biasedlocking)("Revoking bias of object " INTPTR_FORMAT " , mark " |
|
178 INTPTR_FORMAT " , type %s , prototype header " INTPTR_FORMAT |
|
179 " , allow rebias %d , requesting thread " INTPTR_FORMAT, |
|
180 p2i((void *)obj), |
|
181 (intptr_t) mark, |
|
182 obj->klass()->external_name(), |
|
183 (intptr_t) obj->klass()->prototype_header(), |
|
184 (allow_rebias ? 1 : 0), |
|
185 (intptr_t) requesting_thread); |
167 } |
186 } |
168 |
187 |
169 JavaThread* biased_thread = mark->biased_locker(); |
188 JavaThread* biased_thread = mark->biased_locker(); |
170 if (biased_thread == NULL) { |
189 if (biased_thread == NULL) { |
171 // Object is anonymously biased. We can get here if, for |
190 // Object is anonymously biased. We can get here if, for |
172 // example, we revoke the bias due to an identity hash code |
191 // example, we revoke the bias due to an identity hash code |
173 // being computed for an object. |
192 // being computed for an object. |
174 if (!allow_rebias) { |
193 if (!allow_rebias) { |
175 obj->set_mark(unbiased_prototype); |
194 obj->set_mark(unbiased_prototype); |
176 } |
195 } |
177 if (TraceBiasedLocking && (Verbose || !is_bulk)) { |
196 // Log at "info" level if not bulk, else "trace" level |
178 tty->print_cr(" Revoked bias of anonymously-biased object"); |
197 if (!is_bulk) { |
|
198 log_info(biasedlocking)(" Revoked bias of anonymously-biased object"); |
|
199 } else { |
|
200 log_trace(biasedlocking)(" Revoked bias of anonymously-biased object"); |
179 } |
201 } |
180 return BiasedLocking::BIAS_REVOKED; |
202 return BiasedLocking::BIAS_REVOKED; |
181 } |
203 } |
182 |
204 |
183 // Handle case where the thread toward which the object was biased has exited |
205 // Handle case where the thread toward which the object was biased has exited |
212 GrowableArray<MonitorInfo*>* cached_monitor_info = get_or_compute_monitor_info(biased_thread); |
237 GrowableArray<MonitorInfo*>* cached_monitor_info = get_or_compute_monitor_info(biased_thread); |
213 BasicLock* highest_lock = NULL; |
238 BasicLock* highest_lock = NULL; |
214 for (int i = 0; i < cached_monitor_info->length(); i++) { |
239 for (int i = 0; i < cached_monitor_info->length(); i++) { |
215 MonitorInfo* mon_info = cached_monitor_info->at(i); |
240 MonitorInfo* mon_info = cached_monitor_info->at(i); |
216 if (mon_info->owner() == obj) { |
241 if (mon_info->owner() == obj) { |
217 if (TraceBiasedLocking && Verbose) { |
242 log_trace(biasedlocking)(" mon_info->owner (" PTR_FORMAT ") == obj (" PTR_FORMAT ")", |
218 tty->print_cr(" mon_info->owner (" PTR_FORMAT ") == obj (" PTR_FORMAT ")", |
243 p2i((void *) mon_info->owner()), |
219 p2i((void *) mon_info->owner()), |
244 p2i((void *) obj)); |
220 p2i((void *) obj)); |
|
221 } |
|
222 // Assume recursive case and fix up highest lock later |
245 // Assume recursive case and fix up highest lock later |
223 markOop mark = markOopDesc::encode((BasicLock*) NULL); |
246 markOop mark = markOopDesc::encode((BasicLock*) NULL); |
224 highest_lock = mon_info->lock(); |
247 highest_lock = mon_info->lock(); |
225 highest_lock->set_displaced_header(mark); |
248 highest_lock->set_displaced_header(mark); |
226 } else { |
249 } else { |
227 if (TraceBiasedLocking && Verbose) { |
250 log_trace(biasedlocking)(" mon_info->owner (" PTR_FORMAT ") != obj (" PTR_FORMAT ")", |
228 tty->print_cr(" mon_info->owner (" PTR_FORMAT ") != obj (" PTR_FORMAT ")", |
251 p2i((void *) mon_info->owner()), |
229 p2i((void *) mon_info->owner()), |
252 p2i((void *) obj)); |
230 p2i((void *) obj)); |
|
231 } |
|
232 } |
253 } |
233 } |
254 } |
234 if (highest_lock != NULL) { |
255 if (highest_lock != NULL) { |
235 // Fix up highest lock to contain displaced header and point |
256 // Fix up highest lock to contain displaced header and point |
236 // object at it |
257 // object at it |
238 // Reset object header to point to displaced mark. |
259 // Reset object header to point to displaced mark. |
239 // Must release storing the lock address for platforms without TSO |
260 // Must release storing the lock address for platforms without TSO |
240 // ordering (e.g. ppc). |
261 // ordering (e.g. ppc). |
241 obj->release_set_mark(markOopDesc::encode(highest_lock)); |
262 obj->release_set_mark(markOopDesc::encode(highest_lock)); |
242 assert(!obj->mark()->has_bias_pattern(), "illegal mark state: stack lock used bias bit"); |
263 assert(!obj->mark()->has_bias_pattern(), "illegal mark state: stack lock used bias bit"); |
243 if (TraceBiasedLocking && (Verbose || !is_bulk)) { |
264 // Log at "info" level if not bulk, else "trace" level |
244 tty->print_cr(" Revoked bias of currently-locked object"); |
265 if (!is_bulk) { |
|
266 log_info(biasedlocking)(" Revoked bias of currently-locked object"); |
|
267 } else { |
|
268 log_trace(biasedlocking)(" Revoked bias of currently-locked object"); |
245 } |
269 } |
246 } else { |
270 } else { |
247 if (TraceBiasedLocking && (Verbose || !is_bulk)) { |
271 // Log at "info" level if not bulk, else "trace" level |
248 tty->print_cr(" Revoked bias of currently-unlocked object"); |
272 if (!is_bulk) { |
|
273 log_info(biasedlocking)(" Revoked bias of currently-unlocked object"); |
|
274 } else { |
|
275 log_trace(biasedlocking)(" Revoked bias of currently-unlocked object"); |
249 } |
276 } |
250 if (allow_rebias) { |
277 if (allow_rebias) { |
251 obj->set_mark(biased_prototype); |
278 obj->set_mark(biased_prototype); |
252 } else { |
279 } else { |
253 // Store the unlocked value into the object's header. |
280 // Store the unlocked value into the object's header. |
324 bool bulk_rebias, |
351 bool bulk_rebias, |
325 bool attempt_rebias_of_object, |
352 bool attempt_rebias_of_object, |
326 JavaThread* requesting_thread) { |
353 JavaThread* requesting_thread) { |
327 assert(SafepointSynchronize::is_at_safepoint(), "must be done at safepoint"); |
354 assert(SafepointSynchronize::is_at_safepoint(), "must be done at safepoint"); |
328 |
355 |
329 if (TraceBiasedLocking) { |
356 log_info(biasedlocking)("* Beginning bulk revocation (kind == %s) because of object " |
330 tty->print_cr("* Beginning bulk revocation (kind == %s) because of object " |
357 INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s", |
331 INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s", |
358 (bulk_rebias ? "rebias" : "revoke"), |
332 (bulk_rebias ? "rebias" : "revoke"), |
359 p2i((void *) o), |
333 p2i((void *) o), (intptr_t) o->mark(), o->klass()->external_name()); |
360 (intptr_t) o->mark(), |
334 } |
361 o->klass()->external_name()); |
335 |
362 |
336 jlong cur_time = os::javaTimeMillis(); |
363 jlong cur_time = os::javaTimeMillis(); |
337 o->klass()->set_last_biased_lock_bulk_revocation_time(cur_time); |
364 o->klass()->set_last_biased_lock_bulk_revocation_time(cur_time); |
338 |
365 |
339 |
366 |
375 |
402 |
376 // At this point we're done. All we have to do is potentially |
403 // At this point we're done. All we have to do is potentially |
377 // adjust the header of the given object to revoke its bias. |
404 // adjust the header of the given object to revoke its bias. |
378 revoke_bias(o, attempt_rebias_of_object && klass->prototype_header()->has_bias_pattern(), true, requesting_thread); |
405 revoke_bias(o, attempt_rebias_of_object && klass->prototype_header()->has_bias_pattern(), true, requesting_thread); |
379 } else { |
406 } else { |
380 if (TraceBiasedLocking) { |
407 if (log_is_enabled(Info, biasedlocking)) { |
381 ResourceMark rm; |
408 ResourceMark rm; |
382 tty->print_cr("* Disabling biased locking for type %s", klass->external_name()); |
409 log_info(biasedlocking)("* Disabling biased locking for type %s", klass->external_name()); |
383 } |
410 } |
384 |
411 |
385 // Disable biased locking for this data type. Not only will this |
412 // Disable biased locking for this data type. Not only will this |
386 // cause future instances to not be biased, but existing biased |
413 // cause future instances to not be biased, but existing biased |
387 // instances will notice that this implicitly caused their biases |
414 // instances will notice that this implicitly caused their biases |
405 // Must force the bias of the passed object to be forcibly revoked |
432 // Must force the bias of the passed object to be forcibly revoked |
406 // as well to ensure guarantees to callers |
433 // as well to ensure guarantees to callers |
407 revoke_bias(o, false, true, requesting_thread); |
434 revoke_bias(o, false, true, requesting_thread); |
408 } |
435 } |
409 |
436 |
410 if (TraceBiasedLocking) { |
437 log_info(biasedlocking)("* Ending bulk revocation"); |
411 tty->print_cr("* Ending bulk revocation"); |
|
412 } |
|
413 |
438 |
414 BiasedLocking::Condition status_code = BiasedLocking::BIAS_REVOKED; |
439 BiasedLocking::Condition status_code = BiasedLocking::BIAS_REVOKED; |
415 |
440 |
416 if (attempt_rebias_of_object && |
441 if (attempt_rebias_of_object && |
417 o->mark()->has_bias_pattern() && |
442 o->mark()->has_bias_pattern() && |
418 klass->prototype_header()->has_bias_pattern()) { |
443 klass->prototype_header()->has_bias_pattern()) { |
419 markOop new_mark = markOopDesc::encode(requesting_thread, o->mark()->age(), |
444 markOop new_mark = markOopDesc::encode(requesting_thread, o->mark()->age(), |
420 klass->prototype_header()->bias_epoch()); |
445 klass->prototype_header()->bias_epoch()); |
421 o->set_mark(new_mark); |
446 o->set_mark(new_mark); |
422 status_code = BiasedLocking::BIAS_REVOKED_AND_REBIASED; |
447 status_code = BiasedLocking::BIAS_REVOKED_AND_REBIASED; |
423 if (TraceBiasedLocking) { |
448 log_info(biasedlocking)(" Rebiased object toward thread " INTPTR_FORMAT, (intptr_t) requesting_thread); |
424 tty->print_cr(" Rebiased object toward thread " INTPTR_FORMAT, (intptr_t) requesting_thread); |
|
425 } |
|
426 } |
449 } |
427 |
450 |
428 assert(!o->mark()->has_bias_pattern() || |
451 assert(!o->mark()->has_bias_pattern() || |
429 (attempt_rebias_of_object && (o->mark()->biased_locker() == requesting_thread)), |
452 (attempt_rebias_of_object && (o->mark()->biased_locker() == requesting_thread)), |
430 "bug in bulk bias revocation"); |
453 "bug in bulk bias revocation"); |
483 return false; |
506 return false; |
484 } |
507 } |
485 |
508 |
486 virtual void doit() { |
509 virtual void doit() { |
487 if (_obj != NULL) { |
510 if (_obj != NULL) { |
488 if (TraceBiasedLocking) { |
511 log_info(biasedlocking)("Revoking bias with potentially per-thread safepoint:"); |
489 tty->print_cr("Revoking bias with potentially per-thread safepoint:"); |
|
490 } |
|
491 _status_code = revoke_bias((*_obj)(), false, false, _requesting_thread); |
512 _status_code = revoke_bias((*_obj)(), false, false, _requesting_thread); |
492 clean_up_cached_monitor_info(); |
513 clean_up_cached_monitor_info(); |
493 return; |
514 return; |
494 } else { |
515 } else { |
495 if (TraceBiasedLocking) { |
516 log_info(biasedlocking)("Revoking bias with global safepoint:"); |
496 tty->print_cr("Revoking bias with global safepoint:"); |
|
497 } |
|
498 BiasedLocking::revoke_at_safepoint(_objs); |
517 BiasedLocking::revoke_at_safepoint(_objs); |
499 } |
518 } |
500 } |
519 } |
501 |
520 |
502 BiasedLocking::Condition status_code() const { |
521 BiasedLocking::Condition status_code() const { |
606 // reach no safepoints in the revocation path. |
625 // reach no safepoints in the revocation path. |
607 // Also check the epoch because even if threads match, another thread |
626 // Also check the epoch because even if threads match, another thread |
608 // can come in with a CAS to steal the bias of an object that has a |
627 // can come in with a CAS to steal the bias of an object that has a |
609 // stale epoch. |
628 // stale epoch. |
610 ResourceMark rm; |
629 ResourceMark rm; |
611 if (TraceBiasedLocking) { |
630 log_info(biasedlocking)("Revoking bias by walking my own stack:"); |
612 tty->print_cr("Revoking bias by walking my own stack:"); |
|
613 } |
|
614 BiasedLocking::Condition cond = revoke_bias(obj(), false, false, (JavaThread*) THREAD); |
631 BiasedLocking::Condition cond = revoke_bias(obj(), false, false, (JavaThread*) THREAD); |
615 ((JavaThread*) THREAD)->set_cached_monitor_info(NULL); |
632 ((JavaThread*) THREAD)->set_cached_monitor_info(NULL); |
616 assert(cond == BIAS_REVOKED, "why not?"); |
633 assert(cond == BIAS_REVOKED, "why not?"); |
617 return cond; |
634 return cond; |
618 } else { |
635 } else { |