src/hotspot/share/runtime/biasedLocking.cpp
changeset 48105 8d15b1369c7a
parent 47764 029d5efaaa6c
child 49449 ef5d5d343e2a
equal deleted inserted replaced
48096:513e0b467a92 48105:8d15b1369c7a
    30 #include "oops/oop.inline.hpp"
    30 #include "oops/oop.inline.hpp"
    31 #include "runtime/atomic.hpp"
    31 #include "runtime/atomic.hpp"
    32 #include "runtime/basicLock.hpp"
    32 #include "runtime/basicLock.hpp"
    33 #include "runtime/biasedLocking.hpp"
    33 #include "runtime/biasedLocking.hpp"
    34 #include "runtime/task.hpp"
    34 #include "runtime/task.hpp"
       
    35 #include "runtime/threadSMR.hpp"
    35 #include "runtime/vframe.hpp"
    36 #include "runtime/vframe.hpp"
    36 #include "runtime/vmThread.hpp"
    37 #include "runtime/vmThread.hpp"
    37 #include "runtime/vm_operations.hpp"
    38 #include "runtime/vm_operations.hpp"
    38 #include "trace/tracing.hpp"
    39 #include "trace/tracing.hpp"
    39 
    40 
   212   // Handle case where the thread toward which the object was biased has exited
   213   // Handle case where the thread toward which the object was biased has exited
   213   bool thread_is_alive = false;
   214   bool thread_is_alive = false;
   214   if (requesting_thread == biased_thread) {
   215   if (requesting_thread == biased_thread) {
   215     thread_is_alive = true;
   216     thread_is_alive = true;
   216   } else {
   217   } else {
   217     for (JavaThread* cur_thread = Threads::first(); cur_thread != NULL; cur_thread = cur_thread->next()) {
   218     ThreadsListHandle tlh;
   218       if (cur_thread == biased_thread) {
   219     thread_is_alive = tlh.includes(biased_thread);
   219         thread_is_alive = true;
       
   220         break;
       
   221       }
       
   222     }
       
   223   }
   220   }
   224   if (!thread_is_alive) {
   221   if (!thread_is_alive) {
   225     if (allow_rebias) {
   222     if (allow_rebias) {
   226       obj->set_mark(biased_prototype);
   223       obj->set_mark(biased_prototype);
   227     } else {
   224     } else {
   388 
   385 
   389 
   386 
   390   Klass* k_o = o->klass();
   387   Klass* k_o = o->klass();
   391   Klass* klass = k_o;
   388   Klass* klass = k_o;
   392 
   389 
   393   if (bulk_rebias) {
   390   {
   394     // Use the epoch in the klass of the object to implicitly revoke
   391     JavaThreadIteratorWithHandle jtiwh;
   395     // all biases of objects of this data type and force them to be
   392 
   396     // reacquired. However, we also need to walk the stacks of all
   393     if (bulk_rebias) {
   397     // threads and update the headers of lightweight locked objects
   394       // Use the epoch in the klass of the object to implicitly revoke
   398     // with biases to have the current epoch.
   395       // all biases of objects of this data type and force them to be
   399 
   396       // reacquired. However, we also need to walk the stacks of all
   400     // If the prototype header doesn't have the bias pattern, don't
   397       // threads and update the headers of lightweight locked objects
   401     // try to update the epoch -- assume another VM operation came in
   398       // with biases to have the current epoch.
   402     // and reset the header to the unbiased state, which will
   399 
   403     // implicitly cause all existing biases to be revoked
   400       // If the prototype header doesn't have the bias pattern, don't
   404     if (klass->prototype_header()->has_bias_pattern()) {
   401       // try to update the epoch -- assume another VM operation came in
   405       int prev_epoch = klass->prototype_header()->bias_epoch();
   402       // and reset the header to the unbiased state, which will
   406       klass->set_prototype_header(klass->prototype_header()->incr_bias_epoch());
   403       // implicitly cause all existing biases to be revoked
   407       int cur_epoch = klass->prototype_header()->bias_epoch();
   404       if (klass->prototype_header()->has_bias_pattern()) {
   408 
   405         int prev_epoch = klass->prototype_header()->bias_epoch();
   409       // Now walk all threads' stacks and adjust epochs of any biased
   406         klass->set_prototype_header(klass->prototype_header()->incr_bias_epoch());
   410       // and locked objects of this data type we encounter
   407         int cur_epoch = klass->prototype_header()->bias_epoch();
   411       for (JavaThread* thr = Threads::first(); thr != NULL; thr = thr->next()) {
   408 
       
   409         // Now walk all threads' stacks and adjust epochs of any biased
       
   410         // and locked objects of this data type we encounter
       
   411         for (; JavaThread *thr = jtiwh.next(); ) {
       
   412           GrowableArray<MonitorInfo*>* cached_monitor_info = get_or_compute_monitor_info(thr);
       
   413           for (int i = 0; i < cached_monitor_info->length(); i++) {
       
   414             MonitorInfo* mon_info = cached_monitor_info->at(i);
       
   415             oop owner = mon_info->owner();
       
   416             markOop mark = owner->mark();
       
   417             if ((owner->klass() == k_o) && mark->has_bias_pattern()) {
       
   418               // We might have encountered this object already in the case of recursive locking
       
   419               assert(mark->bias_epoch() == prev_epoch || mark->bias_epoch() == cur_epoch, "error in bias epoch adjustment");
       
   420               owner->set_mark(mark->set_bias_epoch(cur_epoch));
       
   421             }
       
   422           }
       
   423         }
       
   424       }
       
   425 
       
   426       // At this point we're done. All we have to do is potentially
       
   427       // adjust the header of the given object to revoke its bias.
       
   428       revoke_bias(o, attempt_rebias_of_object && klass->prototype_header()->has_bias_pattern(), true, requesting_thread, NULL);
       
   429     } else {
       
   430       if (log_is_enabled(Info, biasedlocking)) {
       
   431         ResourceMark rm;
       
   432         log_info(biasedlocking)("* Disabling biased locking for type %s", klass->external_name());
       
   433       }
       
   434 
       
   435       // Disable biased locking for this data type. Not only will this
       
   436       // cause future instances to not be biased, but existing biased
       
   437       // instances will notice that this implicitly caused their biases
       
   438       // to be revoked.
       
   439       klass->set_prototype_header(markOopDesc::prototype());
       
   440 
       
   441       // Now walk all threads' stacks and forcibly revoke the biases of
       
   442       // any locked and biased objects of this data type we encounter.
       
   443       for (; JavaThread *thr = jtiwh.next(); ) {
   412         GrowableArray<MonitorInfo*>* cached_monitor_info = get_or_compute_monitor_info(thr);
   444         GrowableArray<MonitorInfo*>* cached_monitor_info = get_or_compute_monitor_info(thr);
   413         for (int i = 0; i < cached_monitor_info->length(); i++) {
   445         for (int i = 0; i < cached_monitor_info->length(); i++) {
   414           MonitorInfo* mon_info = cached_monitor_info->at(i);
   446           MonitorInfo* mon_info = cached_monitor_info->at(i);
   415           oop owner = mon_info->owner();
   447           oop owner = mon_info->owner();
   416           markOop mark = owner->mark();
   448           markOop mark = owner->mark();
   417           if ((owner->klass() == k_o) && mark->has_bias_pattern()) {
   449           if ((owner->klass() == k_o) && mark->has_bias_pattern()) {
   418             // We might have encountered this object already in the case of recursive locking
   450             revoke_bias(owner, false, true, requesting_thread, NULL);
   419             assert(mark->bias_epoch() == prev_epoch || mark->bias_epoch() == cur_epoch, "error in bias epoch adjustment");
       
   420             owner->set_mark(mark->set_bias_epoch(cur_epoch));
       
   421           }
   451           }
   422         }
   452         }
   423       }
   453       }
   424     }
   454 
   425 
   455       // Must force the bias of the passed object to be forcibly revoked
   426     // At this point we're done. All we have to do is potentially
   456       // as well to ensure guarantees to callers
   427     // adjust the header of the given object to revoke its bias.
   457       revoke_bias(o, false, true, requesting_thread, NULL);
   428     revoke_bias(o, attempt_rebias_of_object && klass->prototype_header()->has_bias_pattern(), true, requesting_thread, NULL);
   458     }
   429   } else {
   459   } // ThreadsListHandle is destroyed here.
   430     if (log_is_enabled(Info, biasedlocking)) {
       
   431       ResourceMark rm;
       
   432       log_info(biasedlocking)("* Disabling biased locking for type %s", klass->external_name());
       
   433     }
       
   434 
       
   435     // Disable biased locking for this data type. Not only will this
       
   436     // cause future instances to not be biased, but existing biased
       
   437     // instances will notice that this implicitly caused their biases
       
   438     // to be revoked.
       
   439     klass->set_prototype_header(markOopDesc::prototype());
       
   440 
       
   441     // Now walk all threads' stacks and forcibly revoke the biases of
       
   442     // any locked and biased objects of this data type we encounter.
       
   443     for (JavaThread* thr = Threads::first(); thr != NULL; thr = thr->next()) {
       
   444       GrowableArray<MonitorInfo*>* cached_monitor_info = get_or_compute_monitor_info(thr);
       
   445       for (int i = 0; i < cached_monitor_info->length(); i++) {
       
   446         MonitorInfo* mon_info = cached_monitor_info->at(i);
       
   447         oop owner = mon_info->owner();
       
   448         markOop mark = owner->mark();
       
   449         if ((owner->klass() == k_o) && mark->has_bias_pattern()) {
       
   450           revoke_bias(owner, false, true, requesting_thread, NULL);
       
   451         }
       
   452       }
       
   453     }
       
   454 
       
   455     // Must force the bias of the passed object to be forcibly revoked
       
   456     // as well to ensure guarantees to callers
       
   457     revoke_bias(o, false, true, requesting_thread, NULL);
       
   458   }
       
   459 
   460 
   460   log_info(biasedlocking)("* Ending bulk revocation");
   461   log_info(biasedlocking)("* Ending bulk revocation");
   461 
   462 
   462   BiasedLocking::Condition status_code = BiasedLocking::BIAS_REVOKED;
   463   BiasedLocking::Condition status_code = BiasedLocking::BIAS_REVOKED;
   463 
   464 
   479 }
   480 }
   480 
   481 
   481 
   482 
   482 static void clean_up_cached_monitor_info() {
   483 static void clean_up_cached_monitor_info() {
   483   // Walk the thread list clearing out the cached monitors
   484   // Walk the thread list clearing out the cached monitors
   484   for (JavaThread* thr = Threads::first(); thr != NULL; thr = thr->next()) {
   485   for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thr = jtiwh.next(); ) {
   485     thr->set_cached_monitor_info(NULL);
   486     thr->set_cached_monitor_info(NULL);
   486   }
   487   }
   487 }
   488 }
   488 
   489 
   489 
   490 
   766   _preserved_mark_stack = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<markOop>(10, true);
   767   _preserved_mark_stack = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<markOop>(10, true);
   767   _preserved_oop_stack = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<Handle>(10, true);
   768   _preserved_oop_stack = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<Handle>(10, true);
   768 
   769 
   769   ResourceMark rm;
   770   ResourceMark rm;
   770   Thread* cur = Thread::current();
   771   Thread* cur = Thread::current();
   771   for (JavaThread* thread = Threads::first(); thread != NULL; thread = thread->next()) {
   772   for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thread = jtiwh.next(); ) {
   772     if (thread->has_last_Java_frame()) {
   773     if (thread->has_last_Java_frame()) {
   773       RegisterMap rm(thread);
   774       RegisterMap rm(thread);
   774       for (javaVFrame* vf = thread->last_java_vframe(&rm); vf != NULL; vf = vf->java_sender()) {
   775       for (javaVFrame* vf = thread->last_java_vframe(&rm); vf != NULL; vf = vf->java_sender()) {
   775         GrowableArray<MonitorInfo*> *monitors = vf->monitors();
   776         GrowableArray<MonitorInfo*> *monitors = vf->monitors();
   776         if (monitors != NULL) {
   777         if (monitors != NULL) {