50 |
50 |
51 static void enable_biased_locking(InstanceKlass* k) { |
51 static void enable_biased_locking(InstanceKlass* k) { |
52 k->set_prototype_header(markOopDesc::biased_locking_prototype()); |
52 k->set_prototype_header(markOopDesc::biased_locking_prototype()); |
53 } |
53 } |
54 |
54 |
|
55 static void enable_biased_locking() { |
|
56 _biased_locking_enabled = true; |
|
57 log_info(biasedlocking)("Biased locking enabled"); |
|
58 } |
|
59 |
55 class VM_EnableBiasedLocking: public VM_Operation { |
60 class VM_EnableBiasedLocking: public VM_Operation { |
56 private: |
|
57 bool _is_cheap_allocated; |
|
58 public: |
61 public: |
59 VM_EnableBiasedLocking(bool is_cheap_allocated) { _is_cheap_allocated = is_cheap_allocated; } |
62 VM_EnableBiasedLocking() {} |
60 VMOp_Type type() const { return VMOp_EnableBiasedLocking; } |
63 VMOp_Type type() const { return VMOp_EnableBiasedLocking; } |
61 Mode evaluation_mode() const { return _is_cheap_allocated ? _async_safepoint : _safepoint; } |
64 Mode evaluation_mode() const { return _async_safepoint; } |
62 bool is_cheap_allocated() const { return _is_cheap_allocated; } |
65 bool is_cheap_allocated() const { return true; } |
63 |
66 |
64 void doit() { |
67 void doit() { |
65 // Iterate the class loader data dictionaries enabling biased locking for all |
68 // Iterate the class loader data dictionaries enabling biased locking for all |
66 // currently loaded classes. |
69 // currently loaded classes. |
67 ClassLoaderDataGraph::dictionary_classes_do(enable_biased_locking); |
70 ClassLoaderDataGraph::dictionary_classes_do(enable_biased_locking); |
68 // Indicate that future instances should enable it as well |
71 // Indicate that future instances should enable it as well |
69 _biased_locking_enabled = true; |
72 enable_biased_locking(); |
70 |
|
71 log_info(biasedlocking)("Biased locking enabled"); |
|
72 } |
73 } |
73 |
74 |
74 bool allow_nested_vm_operations() const { return false; } |
75 bool allow_nested_vm_operations() const { return false; } |
75 }; |
76 }; |
76 |
77 |
81 EnableBiasedLockingTask(size_t interval_time) : PeriodicTask(interval_time) {} |
82 EnableBiasedLockingTask(size_t interval_time) : PeriodicTask(interval_time) {} |
82 |
83 |
83 virtual void task() { |
84 virtual void task() { |
84 // Use async VM operation to avoid blocking the Watcher thread. |
85 // Use async VM operation to avoid blocking the Watcher thread. |
85 // VM Thread will free C heap storage. |
86 // VM Thread will free C heap storage. |
86 VM_EnableBiasedLocking *op = new VM_EnableBiasedLocking(true); |
87 VM_EnableBiasedLocking *op = new VM_EnableBiasedLocking(); |
87 VMThread::execute(op); |
88 VMThread::execute(op); |
88 |
89 |
89 // Reclaim our storage and disenroll ourself |
90 // Reclaim our storage and disenroll ourself |
90 delete this; |
91 delete this; |
91 } |
92 } |
92 }; |
93 }; |
93 |
94 |
94 |
95 |
95 void BiasedLocking::init() { |
96 void BiasedLocking::init() { |
96 // If biased locking is enabled, schedule a task to fire a few |
97 // If biased locking is enabled and BiasedLockingStartupDelay is set, |
97 // seconds into the run which turns on biased locking for all |
98 // schedule a task to fire after the specified delay which turns on |
98 // currently loaded classes as well as future ones. This is a |
99 // biased locking for all currently loaded classes as well as future |
99 // workaround for startup time regressions due to a large number of |
100 // ones. This could be a workaround for startup time regressions |
100 // safepoints being taken during VM startup for bias revocation. |
101 // due to large number of safepoints being taken during VM startup for |
101 // Ideally we would have a lower cost for individual bias revocation |
102 // bias revocation. |
102 // and not need a mechanism like this. |
|
103 if (UseBiasedLocking) { |
103 if (UseBiasedLocking) { |
104 if (BiasedLockingStartupDelay > 0) { |
104 if (BiasedLockingStartupDelay > 0) { |
105 EnableBiasedLockingTask* task = new EnableBiasedLockingTask(BiasedLockingStartupDelay); |
105 EnableBiasedLockingTask* task = new EnableBiasedLockingTask(BiasedLockingStartupDelay); |
106 task->enroll(); |
106 task->enroll(); |
107 } else { |
107 } else { |
108 VM_EnableBiasedLocking op(false); |
108 enable_biased_locking(); |
109 VMThread::execute(&op); |
|
110 } |
109 } |
111 } |
110 } |
112 } |
111 } |
113 |
112 |
114 |
113 |
115 bool BiasedLocking::enabled() { |
114 bool BiasedLocking::enabled() { |
116 return _biased_locking_enabled; |
115 assert(UseBiasedLocking, "precondition"); |
|
116 // We check "BiasedLockingStartupDelay == 0" here to cover the |
|
117 // possibility of calls to BiasedLocking::enabled() before |
|
118 // BiasedLocking::init(). |
|
119 return _biased_locking_enabled || BiasedLockingStartupDelay == 0; |
117 } |
120 } |
118 |
121 |
119 // Returns MonitorInfos for all objects locked on this thread in youngest to oldest order |
122 // Returns MonitorInfos for all objects locked on this thread in youngest to oldest order |
120 static GrowableArray<MonitorInfo*>* get_or_compute_monitor_info(JavaThread* thread) { |
123 static GrowableArray<MonitorInfo*>* get_or_compute_monitor_info(JavaThread* thread) { |
121 GrowableArray<MonitorInfo*>* info = thread->cached_monitor_info(); |
124 GrowableArray<MonitorInfo*>* info = thread->cached_monitor_info(); |