annotate src/share/vm/runtime/biasedLocking.cpp @ 1145:e018e6884bd8

6631166: CMS: better heuristics when combatting fragmentation Summary: Autonomic per-worker free block cache sizing, tunable coalition policies, fixes to per-size block statistics, retuned gain and bandwidth of some feedback loop filters to allow quicker reactivity to abrupt changes in ambient demand, and other heuristics to reduce fragmentation of the CMS old gen. Also tightened some assertions, including those related to locking. Reviewed-by: jmasa
author ysr
date Wed, 23 Dec 2009 09:23:54 -0800
parents bd02caa94611
children c18cbe5936b8
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
844
bd02caa94611 6862919: Update copyright year
xdono
parents: 818
diff changeset
2 * Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
18 *
a61af66fc99e Initial load
duke
parents:
diff changeset
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
a61af66fc99e Initial load
duke
parents:
diff changeset
20 * CA 95054 USA or visit www.sun.com if you need additional information or
a61af66fc99e Initial load
duke
parents:
diff changeset
21 * have any questions.
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
a61af66fc99e Initial load
duke
parents:
diff changeset
25 # include "incls/_precompiled.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
26 # include "incls/_biasedLocking.cpp.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
27
a61af66fc99e Initial load
duke
parents:
diff changeset
28 static bool _biased_locking_enabled = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
29 BiasedLockingCounters BiasedLocking::_counters;
a61af66fc99e Initial load
duke
parents:
diff changeset
30
a61af66fc99e Initial load
duke
parents:
diff changeset
31 static GrowableArray<Handle>* _preserved_oop_stack = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
32 static GrowableArray<markOop>* _preserved_mark_stack = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
33
a61af66fc99e Initial load
duke
parents:
diff changeset
34 static void enable_biased_locking(klassOop k) {
a61af66fc99e Initial load
duke
parents:
diff changeset
35 Klass::cast(k)->set_prototype_header(markOopDesc::biased_locking_prototype());
a61af66fc99e Initial load
duke
parents:
diff changeset
36 }
a61af66fc99e Initial load
duke
parents:
diff changeset
37
a61af66fc99e Initial load
duke
parents:
diff changeset
38 class VM_EnableBiasedLocking: public VM_Operation {
84
6e085831cad7 6692235: Fix for 6666698 broke -XX:BiasedLockingStartupDelay=0
sbohne
parents: 58
diff changeset
39 private:
6e085831cad7 6692235: Fix for 6666698 broke -XX:BiasedLockingStartupDelay=0
sbohne
parents: 58
diff changeset
40 bool _is_cheap_allocated;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
41 public:
84
6e085831cad7 6692235: Fix for 6666698 broke -XX:BiasedLockingStartupDelay=0
sbohne
parents: 58
diff changeset
42 VM_EnableBiasedLocking(bool is_cheap_allocated) { _is_cheap_allocated = is_cheap_allocated; }
58
7ee622712fcf 6666698: EnableBiasedLocking with BiasedLockingStartupDelay can block Watcher thread
sbohne
parents: 0
diff changeset
43 VMOp_Type type() const { return VMOp_EnableBiasedLocking; }
84
6e085831cad7 6692235: Fix for 6666698 broke -XX:BiasedLockingStartupDelay=0
sbohne
parents: 58
diff changeset
44 Mode evaluation_mode() const { return _is_cheap_allocated ? _async_safepoint : _safepoint; }
6e085831cad7 6692235: Fix for 6666698 broke -XX:BiasedLockingStartupDelay=0
sbohne
parents: 58
diff changeset
45 bool is_cheap_allocated() const { return _is_cheap_allocated; }
58
7ee622712fcf 6666698: EnableBiasedLocking with BiasedLockingStartupDelay can block Watcher thread
sbohne
parents: 0
diff changeset
46
0
a61af66fc99e Initial load
duke
parents:
diff changeset
47 void doit() {
a61af66fc99e Initial load
duke
parents:
diff changeset
48 // Iterate the system dictionary enabling biased locking for all
a61af66fc99e Initial load
duke
parents:
diff changeset
49 // currently loaded classes
a61af66fc99e Initial load
duke
parents:
diff changeset
50 SystemDictionary::classes_do(enable_biased_locking);
a61af66fc99e Initial load
duke
parents:
diff changeset
51 // Indicate that future instances should enable it as well
a61af66fc99e Initial load
duke
parents:
diff changeset
52 _biased_locking_enabled = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
53
a61af66fc99e Initial load
duke
parents:
diff changeset
54 if (TraceBiasedLocking) {
a61af66fc99e Initial load
duke
parents:
diff changeset
55 tty->print_cr("Biased locking enabled");
a61af66fc99e Initial load
duke
parents:
diff changeset
56 }
a61af66fc99e Initial load
duke
parents:
diff changeset
57 }
a61af66fc99e Initial load
duke
parents:
diff changeset
58
a61af66fc99e Initial load
duke
parents:
diff changeset
59 bool allow_nested_vm_operations() const { return false; }
a61af66fc99e Initial load
duke
parents:
diff changeset
60 };
a61af66fc99e Initial load
duke
parents:
diff changeset
61
a61af66fc99e Initial load
duke
parents:
diff changeset
62
a61af66fc99e Initial load
duke
parents:
diff changeset
63 // One-shot PeriodicTask subclass for enabling biased locking
a61af66fc99e Initial load
duke
parents:
diff changeset
64 class EnableBiasedLockingTask : public PeriodicTask {
a61af66fc99e Initial load
duke
parents:
diff changeset
65 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
66 EnableBiasedLockingTask(size_t interval_time) : PeriodicTask(interval_time) {}
a61af66fc99e Initial load
duke
parents:
diff changeset
67
a61af66fc99e Initial load
duke
parents:
diff changeset
68 virtual void task() {
58
7ee622712fcf 6666698: EnableBiasedLocking with BiasedLockingStartupDelay can block Watcher thread
sbohne
parents: 0
diff changeset
69 // Use async VM operation to avoid blocking the Watcher thread.
7ee622712fcf 6666698: EnableBiasedLocking with BiasedLockingStartupDelay can block Watcher thread
sbohne
parents: 0
diff changeset
70 // VM Thread will free C heap storage.
84
6e085831cad7 6692235: Fix for 6666698 broke -XX:BiasedLockingStartupDelay=0
sbohne
parents: 58
diff changeset
71 VM_EnableBiasedLocking *op = new VM_EnableBiasedLocking(true);
58
7ee622712fcf 6666698: EnableBiasedLocking with BiasedLockingStartupDelay can block Watcher thread
sbohne
parents: 0
diff changeset
72 VMThread::execute(op);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
73
a61af66fc99e Initial load
duke
parents:
diff changeset
74 // Reclaim our storage and disenroll ourself
a61af66fc99e Initial load
duke
parents:
diff changeset
75 delete this;
a61af66fc99e Initial load
duke
parents:
diff changeset
76 }
a61af66fc99e Initial load
duke
parents:
diff changeset
77 };
a61af66fc99e Initial load
duke
parents:
diff changeset
78
a61af66fc99e Initial load
duke
parents:
diff changeset
79
a61af66fc99e Initial load
duke
parents:
diff changeset
80 void BiasedLocking::init() {
a61af66fc99e Initial load
duke
parents:
diff changeset
81 // If biased locking is enabled, schedule a task to fire a few
a61af66fc99e Initial load
duke
parents:
diff changeset
82 // seconds into the run which turns on biased locking for all
a61af66fc99e Initial load
duke
parents:
diff changeset
83 // currently loaded classes as well as future ones. This is a
a61af66fc99e Initial load
duke
parents:
diff changeset
84 // workaround for startup time regressions due to a large number of
a61af66fc99e Initial load
duke
parents:
diff changeset
85 // safepoints being taken during VM startup for bias revocation.
a61af66fc99e Initial load
duke
parents:
diff changeset
86 // Ideally we would have a lower cost for individual bias revocation
a61af66fc99e Initial load
duke
parents:
diff changeset
87 // and not need a mechanism like this.
a61af66fc99e Initial load
duke
parents:
diff changeset
88 if (UseBiasedLocking) {
a61af66fc99e Initial load
duke
parents:
diff changeset
89 if (BiasedLockingStartupDelay > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
90 EnableBiasedLockingTask* task = new EnableBiasedLockingTask(BiasedLockingStartupDelay);
a61af66fc99e Initial load
duke
parents:
diff changeset
91 task->enroll();
a61af66fc99e Initial load
duke
parents:
diff changeset
92 } else {
84
6e085831cad7 6692235: Fix for 6666698 broke -XX:BiasedLockingStartupDelay=0
sbohne
parents: 58
diff changeset
93 VM_EnableBiasedLocking op(false);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
94 VMThread::execute(&op);
a61af66fc99e Initial load
duke
parents:
diff changeset
95 }
a61af66fc99e Initial load
duke
parents:
diff changeset
96 }
a61af66fc99e Initial load
duke
parents:
diff changeset
97 }
a61af66fc99e Initial load
duke
parents:
diff changeset
98
a61af66fc99e Initial load
duke
parents:
diff changeset
99
a61af66fc99e Initial load
duke
parents:
diff changeset
100 bool BiasedLocking::enabled() {
a61af66fc99e Initial load
duke
parents:
diff changeset
101 return _biased_locking_enabled;
a61af66fc99e Initial load
duke
parents:
diff changeset
102 }
a61af66fc99e Initial load
duke
parents:
diff changeset
103
a61af66fc99e Initial load
duke
parents:
diff changeset
104 // Returns MonitorInfos for all objects locked on this thread in youngest to oldest order
a61af66fc99e Initial load
duke
parents:
diff changeset
105 static GrowableArray<MonitorInfo*>* get_or_compute_monitor_info(JavaThread* thread) {
a61af66fc99e Initial load
duke
parents:
diff changeset
106 GrowableArray<MonitorInfo*>* info = thread->cached_monitor_info();
a61af66fc99e Initial load
duke
parents:
diff changeset
107 if (info != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
108 return info;
a61af66fc99e Initial load
duke
parents:
diff changeset
109 }
a61af66fc99e Initial load
duke
parents:
diff changeset
110
a61af66fc99e Initial load
duke
parents:
diff changeset
111 info = new GrowableArray<MonitorInfo*>();
a61af66fc99e Initial load
duke
parents:
diff changeset
112
a61af66fc99e Initial load
duke
parents:
diff changeset
113 // It's possible for the thread to not have any Java frames on it,
a61af66fc99e Initial load
duke
parents:
diff changeset
114 // i.e., if it's the main thread and it's already returned from main()
a61af66fc99e Initial load
duke
parents:
diff changeset
115 if (thread->has_last_Java_frame()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
116 RegisterMap rm(thread);
a61af66fc99e Initial load
duke
parents:
diff changeset
117 for (javaVFrame* vf = thread->last_java_vframe(&rm); vf != NULL; vf = vf->java_sender()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
118 GrowableArray<MonitorInfo*> *monitors = vf->monitors();
a61af66fc99e Initial load
duke
parents:
diff changeset
119 if (monitors != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
120 int len = monitors->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
121 // Walk monitors youngest to oldest
a61af66fc99e Initial load
duke
parents:
diff changeset
122 for (int i = len - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
123 MonitorInfo* mon_info = monitors->at(i);
818
b109e761e927 6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents: 447
diff changeset
124 if (mon_info->owner_is_scalar_replaced()) continue;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
125 oop owner = mon_info->owner();
a61af66fc99e Initial load
duke
parents:
diff changeset
126 if (owner != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
127 info->append(mon_info);
a61af66fc99e Initial load
duke
parents:
diff changeset
128 }
a61af66fc99e Initial load
duke
parents:
diff changeset
129 }
a61af66fc99e Initial load
duke
parents:
diff changeset
130 }
a61af66fc99e Initial load
duke
parents:
diff changeset
131 }
a61af66fc99e Initial load
duke
parents:
diff changeset
132 }
a61af66fc99e Initial load
duke
parents:
diff changeset
133
a61af66fc99e Initial load
duke
parents:
diff changeset
134 thread->set_cached_monitor_info(info);
a61af66fc99e Initial load
duke
parents:
diff changeset
135 return info;
a61af66fc99e Initial load
duke
parents:
diff changeset
136 }
a61af66fc99e Initial load
duke
parents:
diff changeset
137
a61af66fc99e Initial load
duke
parents:
diff changeset
138
a61af66fc99e Initial load
duke
parents:
diff changeset
139 static BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_bulk, JavaThread* requesting_thread) {
a61af66fc99e Initial load
duke
parents:
diff changeset
140 markOop mark = obj->mark();
a61af66fc99e Initial load
duke
parents:
diff changeset
141 if (!mark->has_bias_pattern()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
142 if (TraceBiasedLocking) {
a61af66fc99e Initial load
duke
parents:
diff changeset
143 ResourceMark rm;
a61af66fc99e Initial load
duke
parents:
diff changeset
144 tty->print_cr(" (Skipping revocation of object of type %s because it's no longer biased)",
a61af66fc99e Initial load
duke
parents:
diff changeset
145 Klass::cast(obj->klass())->external_name());
a61af66fc99e Initial load
duke
parents:
diff changeset
146 }
a61af66fc99e Initial load
duke
parents:
diff changeset
147 return BiasedLocking::NOT_BIASED;
a61af66fc99e Initial load
duke
parents:
diff changeset
148 }
a61af66fc99e Initial load
duke
parents:
diff changeset
149
a61af66fc99e Initial load
duke
parents:
diff changeset
150 int age = mark->age();
a61af66fc99e Initial load
duke
parents:
diff changeset
151 markOop biased_prototype = markOopDesc::biased_locking_prototype()->set_age(age);
a61af66fc99e Initial load
duke
parents:
diff changeset
152 markOop unbiased_prototype = markOopDesc::prototype()->set_age(age);
a61af66fc99e Initial load
duke
parents:
diff changeset
153
a61af66fc99e Initial load
duke
parents:
diff changeset
154 if (TraceBiasedLocking && (Verbose || !is_bulk)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
155 ResourceMark rm;
a61af66fc99e Initial load
duke
parents:
diff changeset
156 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,
a61af66fc99e Initial load
duke
parents:
diff changeset
157 (intptr_t) obj, (intptr_t) mark, Klass::cast(obj->klass())->external_name(), (intptr_t) Klass::cast(obj->klass())->prototype_header(), (allow_rebias ? 1 : 0), (intptr_t) requesting_thread);
a61af66fc99e Initial load
duke
parents:
diff changeset
158 }
a61af66fc99e Initial load
duke
parents:
diff changeset
159
a61af66fc99e Initial load
duke
parents:
diff changeset
160 JavaThread* biased_thread = mark->biased_locker();
a61af66fc99e Initial load
duke
parents:
diff changeset
161 if (biased_thread == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
162 // Object is anonymously biased. We can get here if, for
a61af66fc99e Initial load
duke
parents:
diff changeset
163 // example, we revoke the bias due to an identity hash code
a61af66fc99e Initial load
duke
parents:
diff changeset
164 // being computed for an object.
a61af66fc99e Initial load
duke
parents:
diff changeset
165 if (!allow_rebias) {
a61af66fc99e Initial load
duke
parents:
diff changeset
166 obj->set_mark(unbiased_prototype);
a61af66fc99e Initial load
duke
parents:
diff changeset
167 }
a61af66fc99e Initial load
duke
parents:
diff changeset
168 if (TraceBiasedLocking && (Verbose || !is_bulk)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
169 tty->print_cr(" Revoked bias of anonymously-biased object");
a61af66fc99e Initial load
duke
parents:
diff changeset
170 }
a61af66fc99e Initial load
duke
parents:
diff changeset
171 return BiasedLocking::BIAS_REVOKED;
a61af66fc99e Initial load
duke
parents:
diff changeset
172 }
a61af66fc99e Initial load
duke
parents:
diff changeset
173
a61af66fc99e Initial load
duke
parents:
diff changeset
174 // Handle case where the thread toward which the object was biased has exited
a61af66fc99e Initial load
duke
parents:
diff changeset
175 bool thread_is_alive = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
176 if (requesting_thread == biased_thread) {
a61af66fc99e Initial load
duke
parents:
diff changeset
177 thread_is_alive = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
178 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
179 for (JavaThread* cur_thread = Threads::first(); cur_thread != NULL; cur_thread = cur_thread->next()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
180 if (cur_thread == biased_thread) {
a61af66fc99e Initial load
duke
parents:
diff changeset
181 thread_is_alive = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
182 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
183 }
a61af66fc99e Initial load
duke
parents:
diff changeset
184 }
a61af66fc99e Initial load
duke
parents:
diff changeset
185 }
a61af66fc99e Initial load
duke
parents:
diff changeset
186 if (!thread_is_alive) {
a61af66fc99e Initial load
duke
parents:
diff changeset
187 if (allow_rebias) {
a61af66fc99e Initial load
duke
parents:
diff changeset
188 obj->set_mark(biased_prototype);
a61af66fc99e Initial load
duke
parents:
diff changeset
189 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
190 obj->set_mark(unbiased_prototype);
a61af66fc99e Initial load
duke
parents:
diff changeset
191 }
a61af66fc99e Initial load
duke
parents:
diff changeset
192 if (TraceBiasedLocking && (Verbose || !is_bulk)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
193 tty->print_cr(" Revoked bias of object biased toward dead thread");
a61af66fc99e Initial load
duke
parents:
diff changeset
194 }
a61af66fc99e Initial load
duke
parents:
diff changeset
195 return BiasedLocking::BIAS_REVOKED;
a61af66fc99e Initial load
duke
parents:
diff changeset
196 }
a61af66fc99e Initial load
duke
parents:
diff changeset
197
a61af66fc99e Initial load
duke
parents:
diff changeset
198 // Thread owning bias is alive.
a61af66fc99e Initial load
duke
parents:
diff changeset
199 // Check to see whether it currently owns the lock and, if so,
a61af66fc99e Initial load
duke
parents:
diff changeset
200 // write down the needed displaced headers to the thread's stack.
a61af66fc99e Initial load
duke
parents:
diff changeset
201 // Otherwise, restore the object's header either to the unlocked
a61af66fc99e Initial load
duke
parents:
diff changeset
202 // or unbiased state.
a61af66fc99e Initial load
duke
parents:
diff changeset
203 GrowableArray<MonitorInfo*>* cached_monitor_info = get_or_compute_monitor_info(biased_thread);
a61af66fc99e Initial load
duke
parents:
diff changeset
204 BasicLock* highest_lock = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
205 for (int i = 0; i < cached_monitor_info->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
206 MonitorInfo* mon_info = cached_monitor_info->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
207 if (mon_info->owner() == obj) {
a61af66fc99e Initial load
duke
parents:
diff changeset
208 if (TraceBiasedLocking && Verbose) {
a61af66fc99e Initial load
duke
parents:
diff changeset
209 tty->print_cr(" mon_info->owner (" PTR_FORMAT ") == obj (" PTR_FORMAT ")",
a61af66fc99e Initial load
duke
parents:
diff changeset
210 (intptr_t) mon_info->owner(),
a61af66fc99e Initial load
duke
parents:
diff changeset
211 (intptr_t) obj);
a61af66fc99e Initial load
duke
parents:
diff changeset
212 }
a61af66fc99e Initial load
duke
parents:
diff changeset
213 // Assume recursive case and fix up highest lock later
a61af66fc99e Initial load
duke
parents:
diff changeset
214 markOop mark = markOopDesc::encode((BasicLock*) NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
215 highest_lock = mon_info->lock();
a61af66fc99e Initial load
duke
parents:
diff changeset
216 highest_lock->set_displaced_header(mark);
a61af66fc99e Initial load
duke
parents:
diff changeset
217 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
218 if (TraceBiasedLocking && Verbose) {
a61af66fc99e Initial load
duke
parents:
diff changeset
219 tty->print_cr(" mon_info->owner (" PTR_FORMAT ") != obj (" PTR_FORMAT ")",
a61af66fc99e Initial load
duke
parents:
diff changeset
220 (intptr_t) mon_info->owner(),
a61af66fc99e Initial load
duke
parents:
diff changeset
221 (intptr_t) obj);
a61af66fc99e Initial load
duke
parents:
diff changeset
222 }
a61af66fc99e Initial load
duke
parents:
diff changeset
223 }
a61af66fc99e Initial load
duke
parents:
diff changeset
224 }
a61af66fc99e Initial load
duke
parents:
diff changeset
225 if (highest_lock != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
226 // Fix up highest lock to contain displaced header and point
a61af66fc99e Initial load
duke
parents:
diff changeset
227 // object at it
a61af66fc99e Initial load
duke
parents:
diff changeset
228 highest_lock->set_displaced_header(unbiased_prototype);
a61af66fc99e Initial load
duke
parents:
diff changeset
229 // Reset object header to point to displaced mark
a61af66fc99e Initial load
duke
parents:
diff changeset
230 obj->set_mark(markOopDesc::encode(highest_lock));
a61af66fc99e Initial load
duke
parents:
diff changeset
231 assert(!obj->mark()->has_bias_pattern(), "illegal mark state: stack lock used bias bit");
a61af66fc99e Initial load
duke
parents:
diff changeset
232 if (TraceBiasedLocking && (Verbose || !is_bulk)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
233 tty->print_cr(" Revoked bias of currently-locked object");
a61af66fc99e Initial load
duke
parents:
diff changeset
234 }
a61af66fc99e Initial load
duke
parents:
diff changeset
235 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
236 if (TraceBiasedLocking && (Verbose || !is_bulk)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
237 tty->print_cr(" Revoked bias of currently-unlocked object");
a61af66fc99e Initial load
duke
parents:
diff changeset
238 }
a61af66fc99e Initial load
duke
parents:
diff changeset
239 if (allow_rebias) {
a61af66fc99e Initial load
duke
parents:
diff changeset
240 obj->set_mark(biased_prototype);
a61af66fc99e Initial load
duke
parents:
diff changeset
241 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
242 // Store the unlocked value into the object's header.
a61af66fc99e Initial load
duke
parents:
diff changeset
243 obj->set_mark(unbiased_prototype);
a61af66fc99e Initial load
duke
parents:
diff changeset
244 }
a61af66fc99e Initial load
duke
parents:
diff changeset
245 }
a61af66fc99e Initial load
duke
parents:
diff changeset
246
a61af66fc99e Initial load
duke
parents:
diff changeset
247 return BiasedLocking::BIAS_REVOKED;
a61af66fc99e Initial load
duke
parents:
diff changeset
248 }
a61af66fc99e Initial load
duke
parents:
diff changeset
249
a61af66fc99e Initial load
duke
parents:
diff changeset
250
a61af66fc99e Initial load
duke
parents:
diff changeset
251 enum HeuristicsResult {
a61af66fc99e Initial load
duke
parents:
diff changeset
252 HR_NOT_BIASED = 1,
a61af66fc99e Initial load
duke
parents:
diff changeset
253 HR_SINGLE_REVOKE = 2,
a61af66fc99e Initial load
duke
parents:
diff changeset
254 HR_BULK_REBIAS = 3,
a61af66fc99e Initial load
duke
parents:
diff changeset
255 HR_BULK_REVOKE = 4
a61af66fc99e Initial load
duke
parents:
diff changeset
256 };
a61af66fc99e Initial load
duke
parents:
diff changeset
257
a61af66fc99e Initial load
duke
parents:
diff changeset
258
a61af66fc99e Initial load
duke
parents:
diff changeset
259 static HeuristicsResult update_heuristics(oop o, bool allow_rebias) {
a61af66fc99e Initial load
duke
parents:
diff changeset
260 markOop mark = o->mark();
a61af66fc99e Initial load
duke
parents:
diff changeset
261 if (!mark->has_bias_pattern()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
262 return HR_NOT_BIASED;
a61af66fc99e Initial load
duke
parents:
diff changeset
263 }
a61af66fc99e Initial load
duke
parents:
diff changeset
264
a61af66fc99e Initial load
duke
parents:
diff changeset
265 // Heuristics to attempt to throttle the number of revocations.
a61af66fc99e Initial load
duke
parents:
diff changeset
266 // Stages:
a61af66fc99e Initial load
duke
parents:
diff changeset
267 // 1. Revoke the biases of all objects in the heap of this type,
a61af66fc99e Initial load
duke
parents:
diff changeset
268 // but allow rebiasing of those objects if unlocked.
a61af66fc99e Initial load
duke
parents:
diff changeset
269 // 2. Revoke the biases of all objects in the heap of this type
a61af66fc99e Initial load
duke
parents:
diff changeset
270 // and don't allow rebiasing of these objects. Disable
a61af66fc99e Initial load
duke
parents:
diff changeset
271 // allocation of objects of that type with the bias bit set.
a61af66fc99e Initial load
duke
parents:
diff changeset
272 Klass* k = o->blueprint();
a61af66fc99e Initial load
duke
parents:
diff changeset
273 jlong cur_time = os::javaTimeMillis();
a61af66fc99e Initial load
duke
parents:
diff changeset
274 jlong last_bulk_revocation_time = k->last_biased_lock_bulk_revocation_time();
a61af66fc99e Initial load
duke
parents:
diff changeset
275 int revocation_count = k->biased_lock_revocation_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
276 if ((revocation_count >= BiasedLockingBulkRebiasThreshold) &&
a61af66fc99e Initial load
duke
parents:
diff changeset
277 (revocation_count < BiasedLockingBulkRevokeThreshold) &&
a61af66fc99e Initial load
duke
parents:
diff changeset
278 (last_bulk_revocation_time != 0) &&
a61af66fc99e Initial load
duke
parents:
diff changeset
279 (cur_time - last_bulk_revocation_time >= BiasedLockingDecayTime)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
280 // This is the first revocation we've seen in a while of an
a61af66fc99e Initial load
duke
parents:
diff changeset
281 // object of this type since the last time we performed a bulk
a61af66fc99e Initial load
duke
parents:
diff changeset
282 // rebiasing operation. The application is allocating objects in
a61af66fc99e Initial load
duke
parents:
diff changeset
283 // bulk which are biased toward a thread and then handing them
a61af66fc99e Initial load
duke
parents:
diff changeset
284 // off to another thread. We can cope with this allocation
a61af66fc99e Initial load
duke
parents:
diff changeset
285 // pattern via the bulk rebiasing mechanism so we reset the
a61af66fc99e Initial load
duke
parents:
diff changeset
286 // klass's revocation count rather than allow it to increase
a61af66fc99e Initial load
duke
parents:
diff changeset
287 // monotonically. If we see the need to perform another bulk
a61af66fc99e Initial load
duke
parents:
diff changeset
288 // rebias operation later, we will, and if subsequently we see
a61af66fc99e Initial load
duke
parents:
diff changeset
289 // many more revocation operations in a short period of time we
a61af66fc99e Initial load
duke
parents:
diff changeset
290 // will completely disable biasing for this type.
a61af66fc99e Initial load
duke
parents:
diff changeset
291 k->set_biased_lock_revocation_count(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
292 revocation_count = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
293 }
a61af66fc99e Initial load
duke
parents:
diff changeset
294
a61af66fc99e Initial load
duke
parents:
diff changeset
295 // Make revocation count saturate just beyond BiasedLockingBulkRevokeThreshold
a61af66fc99e Initial load
duke
parents:
diff changeset
296 if (revocation_count <= BiasedLockingBulkRevokeThreshold) {
a61af66fc99e Initial load
duke
parents:
diff changeset
297 revocation_count = k->atomic_incr_biased_lock_revocation_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
298 }
a61af66fc99e Initial load
duke
parents:
diff changeset
299
a61af66fc99e Initial load
duke
parents:
diff changeset
300 if (revocation_count == BiasedLockingBulkRevokeThreshold) {
a61af66fc99e Initial load
duke
parents:
diff changeset
301 return HR_BULK_REVOKE;
a61af66fc99e Initial load
duke
parents:
diff changeset
302 }
a61af66fc99e Initial load
duke
parents:
diff changeset
303
a61af66fc99e Initial load
duke
parents:
diff changeset
304 if (revocation_count == BiasedLockingBulkRebiasThreshold) {
a61af66fc99e Initial load
duke
parents:
diff changeset
305 return HR_BULK_REBIAS;
a61af66fc99e Initial load
duke
parents:
diff changeset
306 }
a61af66fc99e Initial load
duke
parents:
diff changeset
307
a61af66fc99e Initial load
duke
parents:
diff changeset
308 return HR_SINGLE_REVOKE;
a61af66fc99e Initial load
duke
parents:
diff changeset
309 }
a61af66fc99e Initial load
duke
parents:
diff changeset
310
a61af66fc99e Initial load
duke
parents:
diff changeset
311
a61af66fc99e Initial load
duke
parents:
diff changeset
312 static BiasedLocking::Condition bulk_revoke_or_rebias_at_safepoint(oop o,
a61af66fc99e Initial load
duke
parents:
diff changeset
313 bool bulk_rebias,
a61af66fc99e Initial load
duke
parents:
diff changeset
314 bool attempt_rebias_of_object,
a61af66fc99e Initial load
duke
parents:
diff changeset
315 JavaThread* requesting_thread) {
a61af66fc99e Initial load
duke
parents:
diff changeset
316 assert(SafepointSynchronize::is_at_safepoint(), "must be done at safepoint");
a61af66fc99e Initial load
duke
parents:
diff changeset
317
a61af66fc99e Initial load
duke
parents:
diff changeset
318 if (TraceBiasedLocking) {
a61af66fc99e Initial load
duke
parents:
diff changeset
319 tty->print_cr("* Beginning bulk revocation (kind == %s) because of object "
a61af66fc99e Initial load
duke
parents:
diff changeset
320 INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s",
a61af66fc99e Initial load
duke
parents:
diff changeset
321 (bulk_rebias ? "rebias" : "revoke"),
a61af66fc99e Initial load
duke
parents:
diff changeset
322 (intptr_t) o, (intptr_t) o->mark(), Klass::cast(o->klass())->external_name());
a61af66fc99e Initial load
duke
parents:
diff changeset
323 }
a61af66fc99e Initial load
duke
parents:
diff changeset
324
a61af66fc99e Initial load
duke
parents:
diff changeset
325 jlong cur_time = os::javaTimeMillis();
a61af66fc99e Initial load
duke
parents:
diff changeset
326 o->blueprint()->set_last_biased_lock_bulk_revocation_time(cur_time);
a61af66fc99e Initial load
duke
parents:
diff changeset
327
a61af66fc99e Initial load
duke
parents:
diff changeset
328
a61af66fc99e Initial load
duke
parents:
diff changeset
329 klassOop k_o = o->klass();
a61af66fc99e Initial load
duke
parents:
diff changeset
330 Klass* klass = Klass::cast(k_o);
a61af66fc99e Initial load
duke
parents:
diff changeset
331
a61af66fc99e Initial load
duke
parents:
diff changeset
332 if (bulk_rebias) {
a61af66fc99e Initial load
duke
parents:
diff changeset
333 // Use the epoch in the klass of the object to implicitly revoke
a61af66fc99e Initial load
duke
parents:
diff changeset
334 // all biases of objects of this data type and force them to be
a61af66fc99e Initial load
duke
parents:
diff changeset
335 // reacquired. However, we also need to walk the stacks of all
a61af66fc99e Initial load
duke
parents:
diff changeset
336 // threads and update the headers of lightweight locked objects
a61af66fc99e Initial load
duke
parents:
diff changeset
337 // with biases to have the current epoch.
a61af66fc99e Initial load
duke
parents:
diff changeset
338
a61af66fc99e Initial load
duke
parents:
diff changeset
339 // If the prototype header doesn't have the bias pattern, don't
a61af66fc99e Initial load
duke
parents:
diff changeset
340 // try to update the epoch -- assume another VM operation came in
a61af66fc99e Initial load
duke
parents:
diff changeset
341 // and reset the header to the unbiased state, which will
a61af66fc99e Initial load
duke
parents:
diff changeset
342 // implicitly cause all existing biases to be revoked
a61af66fc99e Initial load
duke
parents:
diff changeset
343 if (klass->prototype_header()->has_bias_pattern()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
344 int prev_epoch = klass->prototype_header()->bias_epoch();
a61af66fc99e Initial load
duke
parents:
diff changeset
345 klass->set_prototype_header(klass->prototype_header()->incr_bias_epoch());
a61af66fc99e Initial load
duke
parents:
diff changeset
346 int cur_epoch = klass->prototype_header()->bias_epoch();
a61af66fc99e Initial load
duke
parents:
diff changeset
347
a61af66fc99e Initial load
duke
parents:
diff changeset
348 // Now walk all threads' stacks and adjust epochs of any biased
a61af66fc99e Initial load
duke
parents:
diff changeset
349 // and locked objects of this data type we encounter
a61af66fc99e Initial load
duke
parents:
diff changeset
350 for (JavaThread* thr = Threads::first(); thr != NULL; thr = thr->next()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
351 GrowableArray<MonitorInfo*>* cached_monitor_info = get_or_compute_monitor_info(thr);
a61af66fc99e Initial load
duke
parents:
diff changeset
352 for (int i = 0; i < cached_monitor_info->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
353 MonitorInfo* mon_info = cached_monitor_info->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
354 oop owner = mon_info->owner();
a61af66fc99e Initial load
duke
parents:
diff changeset
355 markOop mark = owner->mark();
a61af66fc99e Initial load
duke
parents:
diff changeset
356 if ((owner->klass() == k_o) && mark->has_bias_pattern()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
357 // We might have encountered this object already in the case of recursive locking
a61af66fc99e Initial load
duke
parents:
diff changeset
358 assert(mark->bias_epoch() == prev_epoch || mark->bias_epoch() == cur_epoch, "error in bias epoch adjustment");
a61af66fc99e Initial load
duke
parents:
diff changeset
359 owner->set_mark(mark->set_bias_epoch(cur_epoch));
a61af66fc99e Initial load
duke
parents:
diff changeset
360 }
a61af66fc99e Initial load
duke
parents:
diff changeset
361 }
a61af66fc99e Initial load
duke
parents:
diff changeset
362 }
a61af66fc99e Initial load
duke
parents:
diff changeset
363 }
a61af66fc99e Initial load
duke
parents:
diff changeset
364
a61af66fc99e Initial load
duke
parents:
diff changeset
365 // At this point we're done. All we have to do is potentially
a61af66fc99e Initial load
duke
parents:
diff changeset
366 // adjust the header of the given object to revoke its bias.
a61af66fc99e Initial load
duke
parents:
diff changeset
367 revoke_bias(o, attempt_rebias_of_object && klass->prototype_header()->has_bias_pattern(), true, requesting_thread);
a61af66fc99e Initial load
duke
parents:
diff changeset
368 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
369 if (TraceBiasedLocking) {
a61af66fc99e Initial load
duke
parents:
diff changeset
370 ResourceMark rm;
a61af66fc99e Initial load
duke
parents:
diff changeset
371 tty->print_cr("* Disabling biased locking for type %s", klass->external_name());
a61af66fc99e Initial load
duke
parents:
diff changeset
372 }
a61af66fc99e Initial load
duke
parents:
diff changeset
373
a61af66fc99e Initial load
duke
parents:
diff changeset
374 // Disable biased locking for this data type. Not only will this
a61af66fc99e Initial load
duke
parents:
diff changeset
375 // cause future instances to not be biased, but existing biased
a61af66fc99e Initial load
duke
parents:
diff changeset
376 // instances will notice that this implicitly caused their biases
a61af66fc99e Initial load
duke
parents:
diff changeset
377 // to be revoked.
a61af66fc99e Initial load
duke
parents:
diff changeset
378 klass->set_prototype_header(markOopDesc::prototype());
a61af66fc99e Initial load
duke
parents:
diff changeset
379
a61af66fc99e Initial load
duke
parents:
diff changeset
380 // Now walk all threads' stacks and forcibly revoke the biases of
a61af66fc99e Initial load
duke
parents:
diff changeset
381 // any locked and biased objects of this data type we encounter.
a61af66fc99e Initial load
duke
parents:
diff changeset
382 for (JavaThread* thr = Threads::first(); thr != NULL; thr = thr->next()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
383 GrowableArray<MonitorInfo*>* cached_monitor_info = get_or_compute_monitor_info(thr);
a61af66fc99e Initial load
duke
parents:
diff changeset
384 for (int i = 0; i < cached_monitor_info->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
385 MonitorInfo* mon_info = cached_monitor_info->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
386 oop owner = mon_info->owner();
a61af66fc99e Initial load
duke
parents:
diff changeset
387 markOop mark = owner->mark();
a61af66fc99e Initial load
duke
parents:
diff changeset
388 if ((owner->klass() == k_o) && mark->has_bias_pattern()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
389 revoke_bias(owner, false, true, requesting_thread);
a61af66fc99e Initial load
duke
parents:
diff changeset
390 }
a61af66fc99e Initial load
duke
parents:
diff changeset
391 }
a61af66fc99e Initial load
duke
parents:
diff changeset
392 }
a61af66fc99e Initial load
duke
parents:
diff changeset
393
a61af66fc99e Initial load
duke
parents:
diff changeset
394 // Must force the bias of the passed object to be forcibly revoked
a61af66fc99e Initial load
duke
parents:
diff changeset
395 // as well to ensure guarantees to callers
a61af66fc99e Initial load
duke
parents:
diff changeset
396 revoke_bias(o, false, true, requesting_thread);
a61af66fc99e Initial load
duke
parents:
diff changeset
397 }
a61af66fc99e Initial load
duke
parents:
diff changeset
398
a61af66fc99e Initial load
duke
parents:
diff changeset
399 if (TraceBiasedLocking) {
a61af66fc99e Initial load
duke
parents:
diff changeset
400 tty->print_cr("* Ending bulk revocation");
a61af66fc99e Initial load
duke
parents:
diff changeset
401 }
a61af66fc99e Initial load
duke
parents:
diff changeset
402
a61af66fc99e Initial load
duke
parents:
diff changeset
403 BiasedLocking::Condition status_code = BiasedLocking::BIAS_REVOKED;
a61af66fc99e Initial load
duke
parents:
diff changeset
404
a61af66fc99e Initial load
duke
parents:
diff changeset
405 if (attempt_rebias_of_object &&
a61af66fc99e Initial load
duke
parents:
diff changeset
406 o->mark()->has_bias_pattern() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
407 klass->prototype_header()->has_bias_pattern()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
408 markOop new_mark = markOopDesc::encode(requesting_thread, o->mark()->age(),
a61af66fc99e Initial load
duke
parents:
diff changeset
409 klass->prototype_header()->bias_epoch());
a61af66fc99e Initial load
duke
parents:
diff changeset
410 o->set_mark(new_mark);
a61af66fc99e Initial load
duke
parents:
diff changeset
411 status_code = BiasedLocking::BIAS_REVOKED_AND_REBIASED;
a61af66fc99e Initial load
duke
parents:
diff changeset
412 if (TraceBiasedLocking) {
a61af66fc99e Initial load
duke
parents:
diff changeset
413 tty->print_cr(" Rebiased object toward thread " INTPTR_FORMAT, (intptr_t) requesting_thread);
a61af66fc99e Initial load
duke
parents:
diff changeset
414 }
a61af66fc99e Initial load
duke
parents:
diff changeset
415 }
a61af66fc99e Initial load
duke
parents:
diff changeset
416
a61af66fc99e Initial load
duke
parents:
diff changeset
417 assert(!o->mark()->has_bias_pattern() ||
a61af66fc99e Initial load
duke
parents:
diff changeset
418 (attempt_rebias_of_object && (o->mark()->biased_locker() == requesting_thread)),
a61af66fc99e Initial load
duke
parents:
diff changeset
419 "bug in bulk bias revocation");
a61af66fc99e Initial load
duke
parents:
diff changeset
420
a61af66fc99e Initial load
duke
parents:
diff changeset
421 return status_code;
a61af66fc99e Initial load
duke
parents:
diff changeset
422 }
a61af66fc99e Initial load
duke
parents:
diff changeset
423
a61af66fc99e Initial load
duke
parents:
diff changeset
424
a61af66fc99e Initial load
duke
parents:
diff changeset
425 static void clean_up_cached_monitor_info() {
a61af66fc99e Initial load
duke
parents:
diff changeset
426 // Walk the thread list clearing out the cached monitors
a61af66fc99e Initial load
duke
parents:
diff changeset
427 for (JavaThread* thr = Threads::first(); thr != NULL; thr = thr->next()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
428 thr->set_cached_monitor_info(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
429 }
a61af66fc99e Initial load
duke
parents:
diff changeset
430 }
a61af66fc99e Initial load
duke
parents:
diff changeset
431
a61af66fc99e Initial load
duke
parents:
diff changeset
432
a61af66fc99e Initial load
duke
parents:
diff changeset
433 class VM_RevokeBias : public VM_Operation {
a61af66fc99e Initial load
duke
parents:
diff changeset
434 protected:
a61af66fc99e Initial load
duke
parents:
diff changeset
435 Handle* _obj;
a61af66fc99e Initial load
duke
parents:
diff changeset
436 GrowableArray<Handle>* _objs;
a61af66fc99e Initial load
duke
parents:
diff changeset
437 JavaThread* _requesting_thread;
a61af66fc99e Initial load
duke
parents:
diff changeset
438 BiasedLocking::Condition _status_code;
a61af66fc99e Initial load
duke
parents:
diff changeset
439
a61af66fc99e Initial load
duke
parents:
diff changeset
440 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
441 VM_RevokeBias(Handle* obj, JavaThread* requesting_thread)
a61af66fc99e Initial load
duke
parents:
diff changeset
442 : _obj(obj)
a61af66fc99e Initial load
duke
parents:
diff changeset
443 , _objs(NULL)
a61af66fc99e Initial load
duke
parents:
diff changeset
444 , _requesting_thread(requesting_thread)
a61af66fc99e Initial load
duke
parents:
diff changeset
445 , _status_code(BiasedLocking::NOT_BIASED) {}
a61af66fc99e Initial load
duke
parents:
diff changeset
446
a61af66fc99e Initial load
duke
parents:
diff changeset
447 VM_RevokeBias(GrowableArray<Handle>* objs, JavaThread* requesting_thread)
a61af66fc99e Initial load
duke
parents:
diff changeset
448 : _obj(NULL)
a61af66fc99e Initial load
duke
parents:
diff changeset
449 , _objs(objs)
a61af66fc99e Initial load
duke
parents:
diff changeset
450 , _requesting_thread(requesting_thread)
a61af66fc99e Initial load
duke
parents:
diff changeset
451 , _status_code(BiasedLocking::NOT_BIASED) {}
a61af66fc99e Initial load
duke
parents:
diff changeset
452
a61af66fc99e Initial load
duke
parents:
diff changeset
453 virtual VMOp_Type type() const { return VMOp_RevokeBias; }
a61af66fc99e Initial load
duke
parents:
diff changeset
454
a61af66fc99e Initial load
duke
parents:
diff changeset
455 virtual bool doit_prologue() {
a61af66fc99e Initial load
duke
parents:
diff changeset
456 // Verify that there is actual work to do since the callers just
a61af66fc99e Initial load
duke
parents:
diff changeset
457 // give us locked object(s). If we don't find any biased objects
a61af66fc99e Initial load
duke
parents:
diff changeset
458 // there is nothing to do and we avoid a safepoint.
a61af66fc99e Initial load
duke
parents:
diff changeset
459 if (_obj != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
460 markOop mark = (*_obj)()->mark();
a61af66fc99e Initial load
duke
parents:
diff changeset
461 if (mark->has_bias_pattern()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
462 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
463 }
a61af66fc99e Initial load
duke
parents:
diff changeset
464 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
465 for ( int i = 0 ; i < _objs->length(); i++ ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
466 markOop mark = (_objs->at(i))()->mark();
a61af66fc99e Initial load
duke
parents:
diff changeset
467 if (mark->has_bias_pattern()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
468 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
469 }
a61af66fc99e Initial load
duke
parents:
diff changeset
470 }
a61af66fc99e Initial load
duke
parents:
diff changeset
471 }
a61af66fc99e Initial load
duke
parents:
diff changeset
472 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
473 }
a61af66fc99e Initial load
duke
parents:
diff changeset
474
a61af66fc99e Initial load
duke
parents:
diff changeset
475 virtual void doit() {
a61af66fc99e Initial load
duke
parents:
diff changeset
476 if (_obj != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
477 if (TraceBiasedLocking) {
a61af66fc99e Initial load
duke
parents:
diff changeset
478 tty->print_cr("Revoking bias with potentially per-thread safepoint:");
a61af66fc99e Initial load
duke
parents:
diff changeset
479 }
a61af66fc99e Initial load
duke
parents:
diff changeset
480 _status_code = revoke_bias((*_obj)(), false, false, _requesting_thread);
a61af66fc99e Initial load
duke
parents:
diff changeset
481 clean_up_cached_monitor_info();
a61af66fc99e Initial load
duke
parents:
diff changeset
482 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
483 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
484 if (TraceBiasedLocking) {
a61af66fc99e Initial load
duke
parents:
diff changeset
485 tty->print_cr("Revoking bias with global safepoint:");
a61af66fc99e Initial load
duke
parents:
diff changeset
486 }
a61af66fc99e Initial load
duke
parents:
diff changeset
487 BiasedLocking::revoke_at_safepoint(_objs);
a61af66fc99e Initial load
duke
parents:
diff changeset
488 }
a61af66fc99e Initial load
duke
parents:
diff changeset
489 }
a61af66fc99e Initial load
duke
parents:
diff changeset
490
a61af66fc99e Initial load
duke
parents:
diff changeset
491 BiasedLocking::Condition status_code() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
492 return _status_code;
a61af66fc99e Initial load
duke
parents:
diff changeset
493 }
a61af66fc99e Initial load
duke
parents:
diff changeset
494 };
a61af66fc99e Initial load
duke
parents:
diff changeset
495
a61af66fc99e Initial load
duke
parents:
diff changeset
496
a61af66fc99e Initial load
duke
parents:
diff changeset
497 class VM_BulkRevokeBias : public VM_RevokeBias {
a61af66fc99e Initial load
duke
parents:
diff changeset
498 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
499 bool _bulk_rebias;
a61af66fc99e Initial load
duke
parents:
diff changeset
500 bool _attempt_rebias_of_object;
a61af66fc99e Initial load
duke
parents:
diff changeset
501
a61af66fc99e Initial load
duke
parents:
diff changeset
502 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
503 VM_BulkRevokeBias(Handle* obj, JavaThread* requesting_thread,
a61af66fc99e Initial load
duke
parents:
diff changeset
504 bool bulk_rebias,
a61af66fc99e Initial load
duke
parents:
diff changeset
505 bool attempt_rebias_of_object)
a61af66fc99e Initial load
duke
parents:
diff changeset
506 : VM_RevokeBias(obj, requesting_thread)
a61af66fc99e Initial load
duke
parents:
diff changeset
507 , _bulk_rebias(bulk_rebias)
a61af66fc99e Initial load
duke
parents:
diff changeset
508 , _attempt_rebias_of_object(attempt_rebias_of_object) {}
a61af66fc99e Initial load
duke
parents:
diff changeset
509
a61af66fc99e Initial load
duke
parents:
diff changeset
510 virtual VMOp_Type type() const { return VMOp_BulkRevokeBias; }
a61af66fc99e Initial load
duke
parents:
diff changeset
511 virtual bool doit_prologue() { return true; }
a61af66fc99e Initial load
duke
parents:
diff changeset
512
a61af66fc99e Initial load
duke
parents:
diff changeset
513 virtual void doit() {
a61af66fc99e Initial load
duke
parents:
diff changeset
514 _status_code = bulk_revoke_or_rebias_at_safepoint((*_obj)(), _bulk_rebias, _attempt_rebias_of_object, _requesting_thread);
a61af66fc99e Initial load
duke
parents:
diff changeset
515 clean_up_cached_monitor_info();
a61af66fc99e Initial load
duke
parents:
diff changeset
516 }
a61af66fc99e Initial load
duke
parents:
diff changeset
517 };
a61af66fc99e Initial load
duke
parents:
diff changeset
518
a61af66fc99e Initial load
duke
parents:
diff changeset
519
a61af66fc99e Initial load
duke
parents:
diff changeset
520 BiasedLocking::Condition BiasedLocking::revoke_and_rebias(Handle obj, bool attempt_rebias, TRAPS) {
a61af66fc99e Initial load
duke
parents:
diff changeset
521 assert(!SafepointSynchronize::is_at_safepoint(), "must not be called while at safepoint");
a61af66fc99e Initial load
duke
parents:
diff changeset
522
a61af66fc99e Initial load
duke
parents:
diff changeset
523 // We can revoke the biases of anonymously-biased objects
a61af66fc99e Initial load
duke
parents:
diff changeset
524 // efficiently enough that we should not cause these revocations to
a61af66fc99e Initial load
duke
parents:
diff changeset
525 // update the heuristics because doing so may cause unwanted bulk
a61af66fc99e Initial load
duke
parents:
diff changeset
526 // revocations (which are expensive) to occur.
a61af66fc99e Initial load
duke
parents:
diff changeset
527 markOop mark = obj->mark();
a61af66fc99e Initial load
duke
parents:
diff changeset
528 if (mark->is_biased_anonymously() && !attempt_rebias) {
a61af66fc99e Initial load
duke
parents:
diff changeset
529 // We are probably trying to revoke the bias of this object due to
a61af66fc99e Initial load
duke
parents:
diff changeset
530 // an identity hash code computation. Try to revoke the bias
a61af66fc99e Initial load
duke
parents:
diff changeset
531 // without a safepoint. This is possible if we can successfully
a61af66fc99e Initial load
duke
parents:
diff changeset
532 // compare-and-exchange an unbiased header into the mark word of
a61af66fc99e Initial load
duke
parents:
diff changeset
533 // the object, meaning that no other thread has raced to acquire
a61af66fc99e Initial load
duke
parents:
diff changeset
534 // the bias of the object.
a61af66fc99e Initial load
duke
parents:
diff changeset
535 markOop biased_value = mark;
a61af66fc99e Initial load
duke
parents:
diff changeset
536 markOop unbiased_prototype = markOopDesc::prototype()->set_age(mark->age());
a61af66fc99e Initial load
duke
parents:
diff changeset
537 markOop res_mark = (markOop) Atomic::cmpxchg_ptr(unbiased_prototype, obj->mark_addr(), mark);
a61af66fc99e Initial load
duke
parents:
diff changeset
538 if (res_mark == biased_value) {
a61af66fc99e Initial load
duke
parents:
diff changeset
539 return BIAS_REVOKED;
a61af66fc99e Initial load
duke
parents:
diff changeset
540 }
a61af66fc99e Initial load
duke
parents:
diff changeset
541 } else if (mark->has_bias_pattern()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
542 Klass* k = Klass::cast(obj->klass());
a61af66fc99e Initial load
duke
parents:
diff changeset
543 markOop prototype_header = k->prototype_header();
a61af66fc99e Initial load
duke
parents:
diff changeset
544 if (!prototype_header->has_bias_pattern()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
545 // This object has a stale bias from before the bulk revocation
a61af66fc99e Initial load
duke
parents:
diff changeset
546 // for this data type occurred. It's pointless to update the
a61af66fc99e Initial load
duke
parents:
diff changeset
547 // heuristics at this point so simply update the header with a
a61af66fc99e Initial load
duke
parents:
diff changeset
548 // CAS. If we fail this race, the object's bias has been revoked
a61af66fc99e Initial load
duke
parents:
diff changeset
549 // by another thread so we simply return and let the caller deal
a61af66fc99e Initial load
duke
parents:
diff changeset
550 // with it.
a61af66fc99e Initial load
duke
parents:
diff changeset
551 markOop biased_value = mark;
a61af66fc99e Initial load
duke
parents:
diff changeset
552 markOop res_mark = (markOop) Atomic::cmpxchg_ptr(prototype_header, obj->mark_addr(), mark);
a61af66fc99e Initial load
duke
parents:
diff changeset
553 assert(!(*(obj->mark_addr()))->has_bias_pattern(), "even if we raced, should still be revoked");
a61af66fc99e Initial load
duke
parents:
diff changeset
554 return BIAS_REVOKED;
a61af66fc99e Initial load
duke
parents:
diff changeset
555 } else if (prototype_header->bias_epoch() != mark->bias_epoch()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
556 // The epoch of this biasing has expired indicating that the
a61af66fc99e Initial load
duke
parents:
diff changeset
557 // object is effectively unbiased. Depending on whether we need
a61af66fc99e Initial load
duke
parents:
diff changeset
558 // to rebias or revoke the bias of this object we can do it
a61af66fc99e Initial load
duke
parents:
diff changeset
559 // efficiently enough with a CAS that we shouldn't update the
a61af66fc99e Initial load
duke
parents:
diff changeset
560 // heuristics. This is normally done in the assembly code but we
a61af66fc99e Initial load
duke
parents:
diff changeset
561 // can reach this point due to various points in the runtime
a61af66fc99e Initial load
duke
parents:
diff changeset
562 // needing to revoke biases.
a61af66fc99e Initial load
duke
parents:
diff changeset
563 if (attempt_rebias) {
a61af66fc99e Initial load
duke
parents:
diff changeset
564 assert(THREAD->is_Java_thread(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
565 markOop biased_value = mark;
a61af66fc99e Initial load
duke
parents:
diff changeset
566 markOop rebiased_prototype = markOopDesc::encode((JavaThread*) THREAD, mark->age(), prototype_header->bias_epoch());
a61af66fc99e Initial load
duke
parents:
diff changeset
567 markOop res_mark = (markOop) Atomic::cmpxchg_ptr(rebiased_prototype, obj->mark_addr(), mark);
a61af66fc99e Initial load
duke
parents:
diff changeset
568 if (res_mark == biased_value) {
a61af66fc99e Initial load
duke
parents:
diff changeset
569 return BIAS_REVOKED_AND_REBIASED;
a61af66fc99e Initial load
duke
parents:
diff changeset
570 }
a61af66fc99e Initial load
duke
parents:
diff changeset
571 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
572 markOop biased_value = mark;
a61af66fc99e Initial load
duke
parents:
diff changeset
573 markOop unbiased_prototype = markOopDesc::prototype()->set_age(mark->age());
a61af66fc99e Initial load
duke
parents:
diff changeset
574 markOop res_mark = (markOop) Atomic::cmpxchg_ptr(unbiased_prototype, obj->mark_addr(), mark);
a61af66fc99e Initial load
duke
parents:
diff changeset
575 if (res_mark == biased_value) {
a61af66fc99e Initial load
duke
parents:
diff changeset
576 return BIAS_REVOKED;
a61af66fc99e Initial load
duke
parents:
diff changeset
577 }
a61af66fc99e Initial load
duke
parents:
diff changeset
578 }
a61af66fc99e Initial load
duke
parents:
diff changeset
579 }
a61af66fc99e Initial load
duke
parents:
diff changeset
580 }
a61af66fc99e Initial load
duke
parents:
diff changeset
581
a61af66fc99e Initial load
duke
parents:
diff changeset
582 HeuristicsResult heuristics = update_heuristics(obj(), attempt_rebias);
a61af66fc99e Initial load
duke
parents:
diff changeset
583 if (heuristics == HR_NOT_BIASED) {
a61af66fc99e Initial load
duke
parents:
diff changeset
584 return NOT_BIASED;
a61af66fc99e Initial load
duke
parents:
diff changeset
585 } else if (heuristics == HR_SINGLE_REVOKE) {
447
2b42b31e7928 6676175: BigApps crash JVM Client VM (build 10.0-b22, mixed mode, sharing) with SIGSEGV (0xb)
coleenp
parents: 196
diff changeset
586 Klass *k = Klass::cast(obj->klass());
2b42b31e7928 6676175: BigApps crash JVM Client VM (build 10.0-b22, mixed mode, sharing) with SIGSEGV (0xb)
coleenp
parents: 196
diff changeset
587 markOop prototype_header = k->prototype_header();
2b42b31e7928 6676175: BigApps crash JVM Client VM (build 10.0-b22, mixed mode, sharing) with SIGSEGV (0xb)
coleenp
parents: 196
diff changeset
588 if (mark->biased_locker() == THREAD &&
2b42b31e7928 6676175: BigApps crash JVM Client VM (build 10.0-b22, mixed mode, sharing) with SIGSEGV (0xb)
coleenp
parents: 196
diff changeset
589 prototype_header->bias_epoch() == mark->bias_epoch()) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
590 // A thread is trying to revoke the bias of an object biased
a61af66fc99e Initial load
duke
parents:
diff changeset
591 // toward it, again likely due to an identity hash code
a61af66fc99e Initial load
duke
parents:
diff changeset
592 // computation. We can again avoid a safepoint in this case
a61af66fc99e Initial load
duke
parents:
diff changeset
593 // since we are only going to walk our own stack. There are no
a61af66fc99e Initial load
duke
parents:
diff changeset
594 // races with revocations occurring in other threads because we
a61af66fc99e Initial load
duke
parents:
diff changeset
595 // reach no safepoints in the revocation path.
447
2b42b31e7928 6676175: BigApps crash JVM Client VM (build 10.0-b22, mixed mode, sharing) with SIGSEGV (0xb)
coleenp
parents: 196
diff changeset
596 // Also check the epoch because even if threads match, another thread
2b42b31e7928 6676175: BigApps crash JVM Client VM (build 10.0-b22, mixed mode, sharing) with SIGSEGV (0xb)
coleenp
parents: 196
diff changeset
597 // can come in with a CAS to steal the bias of an object that has a
2b42b31e7928 6676175: BigApps crash JVM Client VM (build 10.0-b22, mixed mode, sharing) with SIGSEGV (0xb)
coleenp
parents: 196
diff changeset
598 // stale epoch.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
599 ResourceMark rm;
a61af66fc99e Initial load
duke
parents:
diff changeset
600 if (TraceBiasedLocking) {
a61af66fc99e Initial load
duke
parents:
diff changeset
601 tty->print_cr("Revoking bias by walking my own stack:");
a61af66fc99e Initial load
duke
parents:
diff changeset
602 }
a61af66fc99e Initial load
duke
parents:
diff changeset
603 BiasedLocking::Condition cond = revoke_bias(obj(), false, false, (JavaThread*) THREAD);
a61af66fc99e Initial load
duke
parents:
diff changeset
604 ((JavaThread*) THREAD)->set_cached_monitor_info(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
605 assert(cond == BIAS_REVOKED, "why not?");
a61af66fc99e Initial load
duke
parents:
diff changeset
606 return cond;
a61af66fc99e Initial load
duke
parents:
diff changeset
607 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
608 VM_RevokeBias revoke(&obj, (JavaThread*) THREAD);
a61af66fc99e Initial load
duke
parents:
diff changeset
609 VMThread::execute(&revoke);
a61af66fc99e Initial load
duke
parents:
diff changeset
610 return revoke.status_code();
a61af66fc99e Initial load
duke
parents:
diff changeset
611 }
a61af66fc99e Initial load
duke
parents:
diff changeset
612 }
a61af66fc99e Initial load
duke
parents:
diff changeset
613
a61af66fc99e Initial load
duke
parents:
diff changeset
614 assert((heuristics == HR_BULK_REVOKE) ||
a61af66fc99e Initial load
duke
parents:
diff changeset
615 (heuristics == HR_BULK_REBIAS), "?");
a61af66fc99e Initial load
duke
parents:
diff changeset
616 VM_BulkRevokeBias bulk_revoke(&obj, (JavaThread*) THREAD,
a61af66fc99e Initial load
duke
parents:
diff changeset
617 (heuristics == HR_BULK_REBIAS),
a61af66fc99e Initial load
duke
parents:
diff changeset
618 attempt_rebias);
a61af66fc99e Initial load
duke
parents:
diff changeset
619 VMThread::execute(&bulk_revoke);
a61af66fc99e Initial load
duke
parents:
diff changeset
620 return bulk_revoke.status_code();
a61af66fc99e Initial load
duke
parents:
diff changeset
621 }
a61af66fc99e Initial load
duke
parents:
diff changeset
622
a61af66fc99e Initial load
duke
parents:
diff changeset
623
a61af66fc99e Initial load
duke
parents:
diff changeset
624 void BiasedLocking::revoke(GrowableArray<Handle>* objs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
625 assert(!SafepointSynchronize::is_at_safepoint(), "must not be called while at safepoint");
a61af66fc99e Initial load
duke
parents:
diff changeset
626 if (objs->length() == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
627 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
628 }
a61af66fc99e Initial load
duke
parents:
diff changeset
629 VM_RevokeBias revoke(objs, JavaThread::current());
a61af66fc99e Initial load
duke
parents:
diff changeset
630 VMThread::execute(&revoke);
a61af66fc99e Initial load
duke
parents:
diff changeset
631 }
a61af66fc99e Initial load
duke
parents:
diff changeset
632
a61af66fc99e Initial load
duke
parents:
diff changeset
633
a61af66fc99e Initial load
duke
parents:
diff changeset
634 void BiasedLocking::revoke_at_safepoint(Handle h_obj) {
a61af66fc99e Initial load
duke
parents:
diff changeset
635 assert(SafepointSynchronize::is_at_safepoint(), "must only be called while at safepoint");
a61af66fc99e Initial load
duke
parents:
diff changeset
636 oop obj = h_obj();
a61af66fc99e Initial load
duke
parents:
diff changeset
637 HeuristicsResult heuristics = update_heuristics(obj, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
638 if (heuristics == HR_SINGLE_REVOKE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
639 revoke_bias(obj, false, false, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
640 } else if ((heuristics == HR_BULK_REBIAS) ||
a61af66fc99e Initial load
duke
parents:
diff changeset
641 (heuristics == HR_BULK_REVOKE)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
642 bulk_revoke_or_rebias_at_safepoint(obj, (heuristics == HR_BULK_REBIAS), false, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
643 }
a61af66fc99e Initial load
duke
parents:
diff changeset
644 clean_up_cached_monitor_info();
a61af66fc99e Initial load
duke
parents:
diff changeset
645 }
a61af66fc99e Initial load
duke
parents:
diff changeset
646
a61af66fc99e Initial load
duke
parents:
diff changeset
647
a61af66fc99e Initial load
duke
parents:
diff changeset
648 void BiasedLocking::revoke_at_safepoint(GrowableArray<Handle>* objs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
649 assert(SafepointSynchronize::is_at_safepoint(), "must only be called while at safepoint");
a61af66fc99e Initial load
duke
parents:
diff changeset
650 int len = objs->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
651 for (int i = 0; i < len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
652 oop obj = (objs->at(i))();
a61af66fc99e Initial load
duke
parents:
diff changeset
653 HeuristicsResult heuristics = update_heuristics(obj, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
654 if (heuristics == HR_SINGLE_REVOKE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
655 revoke_bias(obj, false, false, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
656 } else if ((heuristics == HR_BULK_REBIAS) ||
a61af66fc99e Initial load
duke
parents:
diff changeset
657 (heuristics == HR_BULK_REVOKE)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
658 bulk_revoke_or_rebias_at_safepoint(obj, (heuristics == HR_BULK_REBIAS), false, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
659 }
a61af66fc99e Initial load
duke
parents:
diff changeset
660 }
a61af66fc99e Initial load
duke
parents:
diff changeset
661 clean_up_cached_monitor_info();
a61af66fc99e Initial load
duke
parents:
diff changeset
662 }
a61af66fc99e Initial load
duke
parents:
diff changeset
663
a61af66fc99e Initial load
duke
parents:
diff changeset
664
a61af66fc99e Initial load
duke
parents:
diff changeset
665 void BiasedLocking::preserve_marks() {
a61af66fc99e Initial load
duke
parents:
diff changeset
666 if (!UseBiasedLocking)
a61af66fc99e Initial load
duke
parents:
diff changeset
667 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
668
a61af66fc99e Initial load
duke
parents:
diff changeset
669 assert(SafepointSynchronize::is_at_safepoint(), "must only be called while at safepoint");
a61af66fc99e Initial load
duke
parents:
diff changeset
670
a61af66fc99e Initial load
duke
parents:
diff changeset
671 assert(_preserved_oop_stack == NULL, "double initialization");
a61af66fc99e Initial load
duke
parents:
diff changeset
672 assert(_preserved_mark_stack == NULL, "double initialization");
a61af66fc99e Initial load
duke
parents:
diff changeset
673
a61af66fc99e Initial load
duke
parents:
diff changeset
674 // In order to reduce the number of mark words preserved during GC
a61af66fc99e Initial load
duke
parents:
diff changeset
675 // due to the presence of biased locking, we reinitialize most mark
a61af66fc99e Initial load
duke
parents:
diff changeset
676 // words to the class's prototype during GC -- even those which have
a61af66fc99e Initial load
duke
parents:
diff changeset
677 // a currently valid bias owner. One important situation where we
a61af66fc99e Initial load
duke
parents:
diff changeset
678 // must not clobber a bias is when a biased object is currently
a61af66fc99e Initial load
duke
parents:
diff changeset
679 // locked. To handle this case we iterate over the currently-locked
a61af66fc99e Initial load
duke
parents:
diff changeset
680 // monitors in a prepass and, if they are biased, preserve their
a61af66fc99e Initial load
duke
parents:
diff changeset
681 // mark words here. This should be a relatively small set of objects
a61af66fc99e Initial load
duke
parents:
diff changeset
682 // especially compared to the number of objects in the heap.
a61af66fc99e Initial load
duke
parents:
diff changeset
683 _preserved_mark_stack = new (ResourceObj::C_HEAP) GrowableArray<markOop>(10, true);
a61af66fc99e Initial load
duke
parents:
diff changeset
684 _preserved_oop_stack = new (ResourceObj::C_HEAP) GrowableArray<Handle>(10, true);
a61af66fc99e Initial load
duke
parents:
diff changeset
685
a61af66fc99e Initial load
duke
parents:
diff changeset
686 ResourceMark rm;
a61af66fc99e Initial load
duke
parents:
diff changeset
687 Thread* cur = Thread::current();
a61af66fc99e Initial load
duke
parents:
diff changeset
688 for (JavaThread* thread = Threads::first(); thread != NULL; thread = thread->next()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
689 if (thread->has_last_Java_frame()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
690 RegisterMap rm(thread);
a61af66fc99e Initial load
duke
parents:
diff changeset
691 for (javaVFrame* vf = thread->last_java_vframe(&rm); vf != NULL; vf = vf->java_sender()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
692 GrowableArray<MonitorInfo*> *monitors = vf->monitors();
a61af66fc99e Initial load
duke
parents:
diff changeset
693 if (monitors != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
694 int len = monitors->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
695 // Walk monitors youngest to oldest
a61af66fc99e Initial load
duke
parents:
diff changeset
696 for (int i = len - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
697 MonitorInfo* mon_info = monitors->at(i);
818
b109e761e927 6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents: 447
diff changeset
698 if (mon_info->owner_is_scalar_replaced()) continue;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
699 oop owner = mon_info->owner();
a61af66fc99e Initial load
duke
parents:
diff changeset
700 if (owner != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
701 markOop mark = owner->mark();
a61af66fc99e Initial load
duke
parents:
diff changeset
702 if (mark->has_bias_pattern()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
703 _preserved_oop_stack->push(Handle(cur, owner));
a61af66fc99e Initial load
duke
parents:
diff changeset
704 _preserved_mark_stack->push(mark);
a61af66fc99e Initial load
duke
parents:
diff changeset
705 }
a61af66fc99e Initial load
duke
parents:
diff changeset
706 }
a61af66fc99e Initial load
duke
parents:
diff changeset
707 }
a61af66fc99e Initial load
duke
parents:
diff changeset
708 }
a61af66fc99e Initial load
duke
parents:
diff changeset
709 }
a61af66fc99e Initial load
duke
parents:
diff changeset
710 }
a61af66fc99e Initial load
duke
parents:
diff changeset
711 }
a61af66fc99e Initial load
duke
parents:
diff changeset
712 }
a61af66fc99e Initial load
duke
parents:
diff changeset
713
a61af66fc99e Initial load
duke
parents:
diff changeset
714
a61af66fc99e Initial load
duke
parents:
diff changeset
715 void BiasedLocking::restore_marks() {
a61af66fc99e Initial load
duke
parents:
diff changeset
716 if (!UseBiasedLocking)
a61af66fc99e Initial load
duke
parents:
diff changeset
717 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
718
a61af66fc99e Initial load
duke
parents:
diff changeset
719 assert(_preserved_oop_stack != NULL, "double free");
a61af66fc99e Initial load
duke
parents:
diff changeset
720 assert(_preserved_mark_stack != NULL, "double free");
a61af66fc99e Initial load
duke
parents:
diff changeset
721
a61af66fc99e Initial load
duke
parents:
diff changeset
722 int len = _preserved_oop_stack->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
723 for (int i = 0; i < len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
724 Handle owner = _preserved_oop_stack->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
725 markOop mark = _preserved_mark_stack->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
726 owner->set_mark(mark);
a61af66fc99e Initial load
duke
parents:
diff changeset
727 }
a61af66fc99e Initial load
duke
parents:
diff changeset
728
a61af66fc99e Initial load
duke
parents:
diff changeset
729 delete _preserved_oop_stack;
a61af66fc99e Initial load
duke
parents:
diff changeset
730 _preserved_oop_stack = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
731 delete _preserved_mark_stack;
a61af66fc99e Initial load
duke
parents:
diff changeset
732 _preserved_mark_stack = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
733 }
a61af66fc99e Initial load
duke
parents:
diff changeset
734
a61af66fc99e Initial load
duke
parents:
diff changeset
735
a61af66fc99e Initial load
duke
parents:
diff changeset
736 int* BiasedLocking::total_entry_count_addr() { return _counters.total_entry_count_addr(); }
a61af66fc99e Initial load
duke
parents:
diff changeset
737 int* BiasedLocking::biased_lock_entry_count_addr() { return _counters.biased_lock_entry_count_addr(); }
a61af66fc99e Initial load
duke
parents:
diff changeset
738 int* BiasedLocking::anonymously_biased_lock_entry_count_addr() { return _counters.anonymously_biased_lock_entry_count_addr(); }
a61af66fc99e Initial load
duke
parents:
diff changeset
739 int* BiasedLocking::rebiased_lock_entry_count_addr() { return _counters.rebiased_lock_entry_count_addr(); }
a61af66fc99e Initial load
duke
parents:
diff changeset
740 int* BiasedLocking::revoked_lock_entry_count_addr() { return _counters.revoked_lock_entry_count_addr(); }
a61af66fc99e Initial load
duke
parents:
diff changeset
741 int* BiasedLocking::fast_path_entry_count_addr() { return _counters.fast_path_entry_count_addr(); }
a61af66fc99e Initial load
duke
parents:
diff changeset
742 int* BiasedLocking::slow_path_entry_count_addr() { return _counters.slow_path_entry_count_addr(); }
a61af66fc99e Initial load
duke
parents:
diff changeset
743
a61af66fc99e Initial load
duke
parents:
diff changeset
744
a61af66fc99e Initial load
duke
parents:
diff changeset
745 // BiasedLockingCounters
a61af66fc99e Initial load
duke
parents:
diff changeset
746
a61af66fc99e Initial load
duke
parents:
diff changeset
747 int BiasedLockingCounters::slow_path_entry_count() {
a61af66fc99e Initial load
duke
parents:
diff changeset
748 if (_slow_path_entry_count != 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
749 return _slow_path_entry_count;
a61af66fc99e Initial load
duke
parents:
diff changeset
750 }
a61af66fc99e Initial load
duke
parents:
diff changeset
751 int sum = _biased_lock_entry_count + _anonymously_biased_lock_entry_count +
a61af66fc99e Initial load
duke
parents:
diff changeset
752 _rebiased_lock_entry_count + _revoked_lock_entry_count +
a61af66fc99e Initial load
duke
parents:
diff changeset
753 _fast_path_entry_count;
a61af66fc99e Initial load
duke
parents:
diff changeset
754
a61af66fc99e Initial load
duke
parents:
diff changeset
755 return _total_entry_count - sum;
a61af66fc99e Initial load
duke
parents:
diff changeset
756 }
a61af66fc99e Initial load
duke
parents:
diff changeset
757
a61af66fc99e Initial load
duke
parents:
diff changeset
758 void BiasedLockingCounters::print_on(outputStream* st) {
a61af66fc99e Initial load
duke
parents:
diff changeset
759 tty->print_cr("# total entries: %d", _total_entry_count);
a61af66fc99e Initial load
duke
parents:
diff changeset
760 tty->print_cr("# biased lock entries: %d", _biased_lock_entry_count);
a61af66fc99e Initial load
duke
parents:
diff changeset
761 tty->print_cr("# anonymously biased lock entries: %d", _anonymously_biased_lock_entry_count);
a61af66fc99e Initial load
duke
parents:
diff changeset
762 tty->print_cr("# rebiased lock entries: %d", _rebiased_lock_entry_count);
a61af66fc99e Initial load
duke
parents:
diff changeset
763 tty->print_cr("# revoked lock entries: %d", _revoked_lock_entry_count);
a61af66fc99e Initial load
duke
parents:
diff changeset
764 tty->print_cr("# fast path lock entries: %d", _fast_path_entry_count);
a61af66fc99e Initial load
duke
parents:
diff changeset
765 tty->print_cr("# slow path lock entries: %d", slow_path_entry_count());
a61af66fc99e Initial load
duke
parents:
diff changeset
766 }