annotate src/share/vm/runtime/synchronizer.cpp @ 3979:4dfb2df418f2

6484982: G1: process references during evacuation pauses Summary: G1 now uses two reference processors - one is used by concurrent marking and the other is used by STW GCs (both full and incremental evacuation pauses). In an evacuation pause, the reference processor is embedded into the closures used to scan objects. Doing so causes causes reference objects to be 'discovered' by the reference processor. At the end of the evacuation pause, these discovered reference objects are processed - preserving (and copying) referent objects (and their reachable graphs) as appropriate. Reviewed-by: ysr, jwilhelm, brutisso, stefank, tonyp
author johnc
date Thu, 22 Sep 2011 10:57:37 -0700
parents 1d1603768966
children 0654ee04b214 f08d439fab8c
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
2426
1d1603768966 7010070: Update all 2010 Oracle-changed OpenJDK files to have the proper copyright dates - second pass
trims
parents: 2177
diff changeset
2 * Copyright (c) 1998, 2011, Oracle and/or its affiliates. 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 *
1552
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 702
diff changeset
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 702
diff changeset
20 * or visit www.oracle.com if you need additional information or have any
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 702
diff changeset
21 * questions.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
1972
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
25 #include "precompiled.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
26 #include "classfile/vmSymbols.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
27 #include "memory/resourceArea.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
28 #include "oops/markOop.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
29 #include "oops/oop.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
30 #include "runtime/biasedLocking.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
31 #include "runtime/handles.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
32 #include "runtime/interfaceSupport.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
33 #include "runtime/mutexLocker.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
34 #include "runtime/objectMonitor.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
35 #include "runtime/objectMonitor.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
36 #include "runtime/osThread.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
37 #include "runtime/stubRoutines.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
38 #include "runtime/synchronizer.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
39 #include "utilities/dtrace.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
40 #include "utilities/events.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
41 #include "utilities/preserveException.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
42 #ifdef TARGET_OS_FAMILY_linux
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
43 # include "os_linux.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
44 # include "thread_linux.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
45 #endif
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
46 #ifdef TARGET_OS_FAMILY_solaris
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
47 # include "os_solaris.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
48 # include "thread_solaris.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
49 #endif
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
50 #ifdef TARGET_OS_FAMILY_windows
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
51 # include "os_windows.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
52 # include "thread_windows.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1878
diff changeset
53 #endif
0
a61af66fc99e Initial load
duke
parents:
diff changeset
54
a61af66fc99e Initial load
duke
parents:
diff changeset
55 #if defined(__GNUC__) && !defined(IA64)
a61af66fc99e Initial load
duke
parents:
diff changeset
56 // Need to inhibit inlining for older versions of GCC to avoid build-time failures
a61af66fc99e Initial load
duke
parents:
diff changeset
57 #define ATTR __attribute__((noinline))
a61af66fc99e Initial load
duke
parents:
diff changeset
58 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
59 #define ATTR
a61af66fc99e Initial load
duke
parents:
diff changeset
60 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
61
a61af66fc99e Initial load
duke
parents:
diff changeset
62 // The "core" versions of monitor enter and exit reside in this file.
a61af66fc99e Initial load
duke
parents:
diff changeset
63 // The interpreter and compilers contain specialized transliterated
a61af66fc99e Initial load
duke
parents:
diff changeset
64 // variants of the enter-exit fast-path operations. See i486.ad fast_lock(),
a61af66fc99e Initial load
duke
parents:
diff changeset
65 // for instance. If you make changes here, make sure to modify the
a61af66fc99e Initial load
duke
parents:
diff changeset
66 // interpreter, and both C1 and C2 fast-path inline locking code emission.
a61af66fc99e Initial load
duke
parents:
diff changeset
67 //
a61af66fc99e Initial load
duke
parents:
diff changeset
68 //
a61af66fc99e Initial load
duke
parents:
diff changeset
69 // -----------------------------------------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
70
a61af66fc99e Initial load
duke
parents:
diff changeset
71 #ifdef DTRACE_ENABLED
a61af66fc99e Initial load
duke
parents:
diff changeset
72
a61af66fc99e Initial load
duke
parents:
diff changeset
73 // Only bother with this argument setup if dtrace is available
a61af66fc99e Initial load
duke
parents:
diff changeset
74 // TODO-FIXME: probes should not fire when caller is _blocked. assert() accordingly.
a61af66fc99e Initial load
duke
parents:
diff changeset
75
a61af66fc99e Initial load
duke
parents:
diff changeset
76 HS_DTRACE_PROBE_DECL5(hotspot, monitor__wait,
a61af66fc99e Initial load
duke
parents:
diff changeset
77 jlong, uintptr_t, char*, int, long);
a61af66fc99e Initial load
duke
parents:
diff changeset
78 HS_DTRACE_PROBE_DECL4(hotspot, monitor__waited,
a61af66fc99e Initial load
duke
parents:
diff changeset
79 jlong, uintptr_t, char*, int);
a61af66fc99e Initial load
duke
parents:
diff changeset
80
a61af66fc99e Initial load
duke
parents:
diff changeset
81 #define DTRACE_MONITOR_PROBE_COMMON(klassOop, thread) \
a61af66fc99e Initial load
duke
parents:
diff changeset
82 char* bytes = NULL; \
a61af66fc99e Initial load
duke
parents:
diff changeset
83 int len = 0; \
a61af66fc99e Initial load
duke
parents:
diff changeset
84 jlong jtid = SharedRuntime::get_java_tid(thread); \
2177
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
85 Symbol* klassname = ((oop)(klassOop))->klass()->klass_part()->name(); \
0
a61af66fc99e Initial load
duke
parents:
diff changeset
86 if (klassname != NULL) { \
a61af66fc99e Initial load
duke
parents:
diff changeset
87 bytes = (char*)klassname->bytes(); \
a61af66fc99e Initial load
duke
parents:
diff changeset
88 len = klassname->utf8_length(); \
a61af66fc99e Initial load
duke
parents:
diff changeset
89 }
a61af66fc99e Initial load
duke
parents:
diff changeset
90
a61af66fc99e Initial load
duke
parents:
diff changeset
91 #define DTRACE_MONITOR_WAIT_PROBE(monitor, klassOop, thread, millis) \
a61af66fc99e Initial load
duke
parents:
diff changeset
92 { \
a61af66fc99e Initial load
duke
parents:
diff changeset
93 if (DTraceMonitorProbes) { \
a61af66fc99e Initial load
duke
parents:
diff changeset
94 DTRACE_MONITOR_PROBE_COMMON(klassOop, thread); \
a61af66fc99e Initial load
duke
parents:
diff changeset
95 HS_DTRACE_PROBE5(hotspot, monitor__wait, jtid, \
a61af66fc99e Initial load
duke
parents:
diff changeset
96 (monitor), bytes, len, (millis)); \
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 #define DTRACE_MONITOR_PROBE(probe, monitor, klassOop, thread) \
a61af66fc99e Initial load
duke
parents:
diff changeset
101 { \
a61af66fc99e Initial load
duke
parents:
diff changeset
102 if (DTraceMonitorProbes) { \
a61af66fc99e Initial load
duke
parents:
diff changeset
103 DTRACE_MONITOR_PROBE_COMMON(klassOop, thread); \
a61af66fc99e Initial load
duke
parents:
diff changeset
104 HS_DTRACE_PROBE4(hotspot, monitor__##probe, jtid, \
a61af66fc99e Initial load
duke
parents:
diff changeset
105 (uintptr_t)(monitor), bytes, len); \
a61af66fc99e Initial load
duke
parents:
diff changeset
106 } \
a61af66fc99e Initial load
duke
parents:
diff changeset
107 }
a61af66fc99e Initial load
duke
parents:
diff changeset
108
a61af66fc99e Initial load
duke
parents:
diff changeset
109 #else // ndef DTRACE_ENABLED
a61af66fc99e Initial load
duke
parents:
diff changeset
110
a61af66fc99e Initial load
duke
parents:
diff changeset
111 #define DTRACE_MONITOR_WAIT_PROBE(klassOop, thread, millis, mon) {;}
a61af66fc99e Initial load
duke
parents:
diff changeset
112 #define DTRACE_MONITOR_PROBE(probe, klassOop, thread, mon) {;}
a61af66fc99e Initial load
duke
parents:
diff changeset
113
a61af66fc99e Initial load
duke
parents:
diff changeset
114 #endif // ndef DTRACE_ENABLED
a61af66fc99e Initial load
duke
parents:
diff changeset
115
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
116 // This exists only as a workaround of dtrace bug 6254741
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
117 int dtrace_waited_probe(ObjectMonitor* monitor, Handle obj, Thread* thr) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
118 DTRACE_MONITOR_PROBE(waited, monitor, obj(), thr);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
119 return 0;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
120 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
121
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
122 #define NINFLATIONLOCKS 256
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
123 static volatile intptr_t InflationLocks [NINFLATIONLOCKS] ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
124
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
125 ObjectMonitor * ObjectSynchronizer::gBlockList = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
126 ObjectMonitor * volatile ObjectSynchronizer::gFreeList = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
127 ObjectMonitor * volatile ObjectSynchronizer::gOmInUseList = NULL ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
128 int ObjectSynchronizer::gOmInUseCount = 0;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
129 static volatile intptr_t ListLock = 0 ; // protects global monitor free-list cache
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
130 static volatile int MonitorFreeCount = 0 ; // # on gFreeList
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
131 static volatile int MonitorPopulation = 0 ; // # Extant -- in circulation
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
132 #define CHAINMARKER ((oop)-1)
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
133
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
134 // -----------------------------------------------------------------------------
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
135 // Fast Monitor Enter/Exit
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
136 // This the fast monitor enter. The interpreter and compiler use
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
137 // some assembly copies of this code. Make sure update those code
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
138 // if the following function is changed. The implementation is
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
139 // extremely sensitive to race condition. Be careful.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
140
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
141 void ObjectSynchronizer::fast_enter(Handle obj, BasicLock* lock, bool attempt_rebias, TRAPS) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
142 if (UseBiasedLocking) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
143 if (!SafepointSynchronize::is_at_safepoint()) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
144 BiasedLocking::Condition cond = BiasedLocking::revoke_and_rebias(obj, attempt_rebias, THREAD);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
145 if (cond == BiasedLocking::BIAS_REVOKED_AND_REBIASED) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
146 return;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
147 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
148 } else {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
149 assert(!attempt_rebias, "can not rebias toward VM thread");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
150 BiasedLocking::revoke_at_safepoint(obj);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
151 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
152 assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
153 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
154
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
155 slow_enter (obj, lock, THREAD) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
156 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
157
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
158 void ObjectSynchronizer::fast_exit(oop object, BasicLock* lock, TRAPS) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
159 assert(!object->mark()->has_bias_pattern(), "should not see bias pattern here");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
160 // if displaced header is null, the previous enter is recursive enter, no-op
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
161 markOop dhw = lock->displaced_header();
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
162 markOop mark ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
163 if (dhw == NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
164 // Recursive stack-lock.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
165 // Diagnostics -- Could be: stack-locked, inflating, inflated.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
166 mark = object->mark() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
167 assert (!mark->is_neutral(), "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
168 if (mark->has_locker() && mark != markOopDesc::INFLATING()) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
169 assert(THREAD->is_lock_owned((address)mark->locker()), "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
170 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
171 if (mark->has_monitor()) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
172 ObjectMonitor * m = mark->monitor() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
173 assert(((oop)(m->object()))->mark() == mark, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
174 assert(m->is_entered(THREAD), "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
175 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
176 return ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
177 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
178
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
179 mark = object->mark() ;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
180
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
181 // If the object is stack-locked by the current thread, try to
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
182 // swing the displaced header from the box back to the mark.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
183 if (mark == (markOop) lock) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
184 assert (dhw->is_neutral(), "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
185 if ((markOop) Atomic::cmpxchg_ptr (dhw, object->mark_addr(), mark) == mark) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
186 TEVENT (fast_exit: release stacklock) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
187 return;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
188 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
189 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
190
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
191 ObjectSynchronizer::inflate(THREAD, object)->exit (THREAD) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
192 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
193
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
194 // -----------------------------------------------------------------------------
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
195 // Interpreter/Compiler Slow Case
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
196 // This routine is used to handle interpreter/compiler slow case
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
197 // We don't need to use fast path here, because it must have been
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
198 // failed in the interpreter/compiler code.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
199 void ObjectSynchronizer::slow_enter(Handle obj, BasicLock* lock, TRAPS) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
200 markOop mark = obj->mark();
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
201 assert(!mark->has_bias_pattern(), "should not see bias pattern here");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
202
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
203 if (mark->is_neutral()) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
204 // Anticipate successful CAS -- the ST of the displaced mark must
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
205 // be visible <= the ST performed by the CAS.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
206 lock->set_displaced_header(mark);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
207 if (mark == (markOop) Atomic::cmpxchg_ptr(lock, obj()->mark_addr(), mark)) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
208 TEVENT (slow_enter: release stacklock) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
209 return ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
210 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
211 // Fall through to inflate() ...
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
212 } else
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
213 if (mark->has_locker() && THREAD->is_lock_owned((address)mark->locker())) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
214 assert(lock != mark->locker(), "must not re-lock the same lock");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
215 assert(lock != (BasicLock*)obj->mark(), "don't relock with same BasicLock");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
216 lock->set_displaced_header(NULL);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
217 return;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
218 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
219
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
220 #if 0
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
221 // The following optimization isn't particularly useful.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
222 if (mark->has_monitor() && mark->monitor()->is_entered(THREAD)) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
223 lock->set_displaced_header (NULL) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
224 return ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
225 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
226 #endif
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
227
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
228 // The object header will never be displaced to this lock,
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
229 // so it does not matter what the value is, except that it
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
230 // must be non-zero to avoid looking like a re-entrant lock,
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
231 // and must not look locked either.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
232 lock->set_displaced_header(markOopDesc::unused_mark());
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
233 ObjectSynchronizer::inflate(THREAD, obj())->enter(THREAD);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
234 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
235
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
236 // This routine is used to handle interpreter/compiler slow case
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
237 // We don't need to use fast path here, because it must have
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
238 // failed in the interpreter/compiler code. Simply use the heavy
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
239 // weight monitor should be ok, unless someone find otherwise.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
240 void ObjectSynchronizer::slow_exit(oop object, BasicLock* lock, TRAPS) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
241 fast_exit (object, lock, THREAD) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
242 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
243
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
244 // -----------------------------------------------------------------------------
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
245 // Class Loader support to workaround deadlocks on the class loader lock objects
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
246 // Also used by GC
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
247 // complete_exit()/reenter() are used to wait on a nested lock
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
248 // i.e. to give up an outer lock completely and then re-enter
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
249 // Used when holding nested locks - lock acquisition order: lock1 then lock2
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
250 // 1) complete_exit lock1 - saving recursion count
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
251 // 2) wait on lock2
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
252 // 3) when notified on lock2, unlock lock2
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
253 // 4) reenter lock1 with original recursion count
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
254 // 5) lock lock2
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
255 // NOTE: must use heavy weight monitor to handle complete_exit/reenter()
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
256 intptr_t ObjectSynchronizer::complete_exit(Handle obj, TRAPS) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
257 TEVENT (complete_exit) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
258 if (UseBiasedLocking) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
259 BiasedLocking::revoke_and_rebias(obj, false, THREAD);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
260 assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
261 }
a61af66fc99e Initial load
duke
parents:
diff changeset
262
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
263 ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD, obj());
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
264
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
265 return monitor->complete_exit(THREAD);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
266 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
267
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
268 // NOTE: must use heavy weight monitor to handle complete_exit/reenter()
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
269 void ObjectSynchronizer::reenter(Handle obj, intptr_t recursion, TRAPS) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
270 TEVENT (reenter) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
271 if (UseBiasedLocking) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
272 BiasedLocking::revoke_and_rebias(obj, false, THREAD);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
273 assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
274 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
275
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
276 ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD, obj());
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
277
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
278 monitor->reenter(recursion, THREAD);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
279 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
280 // -----------------------------------------------------------------------------
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
281 // JNI locks on java objects
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
282 // NOTE: must use heavy weight monitor to handle jni monitor enter
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
283 void ObjectSynchronizer::jni_enter(Handle obj, TRAPS) { // possible entry from jni enter
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
284 // the current locking is from JNI instead of Java code
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
285 TEVENT (jni_enter) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
286 if (UseBiasedLocking) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
287 BiasedLocking::revoke_and_rebias(obj, false, THREAD);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
288 assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
289 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
290 THREAD->set_current_pending_monitor_is_from_java(false);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
291 ObjectSynchronizer::inflate(THREAD, obj())->enter(THREAD);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
292 THREAD->set_current_pending_monitor_is_from_java(true);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
293 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
294
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
295 // NOTE: must use heavy weight monitor to handle jni monitor enter
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
296 bool ObjectSynchronizer::jni_try_enter(Handle obj, Thread* THREAD) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
297 if (UseBiasedLocking) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
298 BiasedLocking::revoke_and_rebias(obj, false, THREAD);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
299 assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
300 }
a61af66fc99e Initial load
duke
parents:
diff changeset
301
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
302 ObjectMonitor* monitor = ObjectSynchronizer::inflate_helper(obj());
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
303 return monitor->try_enter(THREAD);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
304 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
305
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
306
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
307 // NOTE: must use heavy weight monitor to handle jni monitor exit
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
308 void ObjectSynchronizer::jni_exit(oop obj, Thread* THREAD) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
309 TEVENT (jni_exit) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
310 if (UseBiasedLocking) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
311 BiasedLocking::revoke_and_rebias(obj, false, THREAD);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
312 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
313 assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
314
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
315 ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD, obj);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
316 // If this thread has locked the object, exit the monitor. Note: can't use
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
317 // monitor->check(CHECK); must exit even if an exception is pending.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
318 if (monitor->check(THREAD)) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
319 monitor->exit(THREAD);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
320 }
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
321 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
322
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
323 // -----------------------------------------------------------------------------
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
324 // Internal VM locks on java objects
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
325 // standard constructor, allows locking failures
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
326 ObjectLocker::ObjectLocker(Handle obj, Thread* thread, bool doLock) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
327 _dolock = doLock;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
328 _thread = thread;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
329 debug_only(if (StrictSafepointChecks) _thread->check_for_valid_safepoint_state(false);)
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
330 _obj = obj;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
331
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
332 if (_dolock) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
333 TEVENT (ObjectLocker) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
334
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
335 ObjectSynchronizer::fast_enter(_obj, &_lock, false, _thread);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
336 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
337 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
338
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
339 ObjectLocker::~ObjectLocker() {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
340 if (_dolock) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
341 ObjectSynchronizer::fast_exit(_obj(), &_lock, _thread);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
342 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
343 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
344
a61af66fc99e Initial load
duke
parents:
diff changeset
345
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
346 // -----------------------------------------------------------------------------
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
347 // Wait/Notify/NotifyAll
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
348 // NOTE: must use heavy weight monitor to handle wait()
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
349 void ObjectSynchronizer::wait(Handle obj, jlong millis, TRAPS) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
350 if (UseBiasedLocking) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
351 BiasedLocking::revoke_and_rebias(obj, false, THREAD);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
352 assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
353 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
354 if (millis < 0) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
355 TEVENT (wait - throw IAX) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
356 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
357 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
358 ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD, obj());
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
359 DTRACE_MONITOR_WAIT_PROBE(monitor, obj(), THREAD, millis);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
360 monitor->wait(millis, true, THREAD);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
361
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
362 /* This dummy call is in place to get around dtrace bug 6254741. Once
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
363 that's fixed we can uncomment the following line and remove the call */
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
364 // DTRACE_MONITOR_PROBE(waited, monitor, obj(), THREAD);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
365 dtrace_waited_probe(monitor, obj, THREAD);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
366 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
367
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
368 void ObjectSynchronizer::waitUninterruptibly (Handle obj, jlong millis, TRAPS) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
369 if (UseBiasedLocking) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
370 BiasedLocking::revoke_and_rebias(obj, false, THREAD);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
371 assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
372 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
373 if (millis < 0) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
374 TEVENT (wait - throw IAX) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
375 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
376 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
377 ObjectSynchronizer::inflate(THREAD, obj()) -> wait(millis, false, THREAD) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
378 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
379
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
380 void ObjectSynchronizer::notify(Handle obj, TRAPS) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
381 if (UseBiasedLocking) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
382 BiasedLocking::revoke_and_rebias(obj, false, THREAD);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
383 assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
384 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
385
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
386 markOop mark = obj->mark();
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
387 if (mark->has_locker() && THREAD->is_lock_owned((address)mark->locker())) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
388 return;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
389 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
390 ObjectSynchronizer::inflate(THREAD, obj())->notify(THREAD);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
391 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
392
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
393 // NOTE: see comment of notify()
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
394 void ObjectSynchronizer::notifyall(Handle obj, TRAPS) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
395 if (UseBiasedLocking) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
396 BiasedLocking::revoke_and_rebias(obj, false, THREAD);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
397 assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
398 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
399
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
400 markOop mark = obj->mark();
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
401 if (mark->has_locker() && THREAD->is_lock_owned((address)mark->locker())) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
402 return;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
403 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
404 ObjectSynchronizer::inflate(THREAD, obj())->notifyAll(THREAD);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
405 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
406
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
407 // -----------------------------------------------------------------------------
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
408 // Hash Code handling
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
409 //
0
a61af66fc99e Initial load
duke
parents:
diff changeset
410 // Performance concern:
a61af66fc99e Initial load
duke
parents:
diff changeset
411 // OrderAccess::storestore() calls release() which STs 0 into the global volatile
a61af66fc99e Initial load
duke
parents:
diff changeset
412 // OrderAccess::Dummy variable. This store is unnecessary for correctness.
a61af66fc99e Initial load
duke
parents:
diff changeset
413 // Many threads STing into a common location causes considerable cache migration
a61af66fc99e Initial load
duke
parents:
diff changeset
414 // or "sloshing" on large SMP system. As such, I avoid using OrderAccess::storestore()
a61af66fc99e Initial load
duke
parents:
diff changeset
415 // until it's repaired. In some cases OrderAccess::fence() -- which incurs local
a61af66fc99e Initial load
duke
parents:
diff changeset
416 // latency on the executing processor -- is a better choice as it scales on SMP
a61af66fc99e Initial load
duke
parents:
diff changeset
417 // systems. See http://blogs.sun.com/dave/entry/biased_locking_in_hotspot for a
a61af66fc99e Initial load
duke
parents:
diff changeset
418 // discussion of coherency costs. Note that all our current reference platforms
a61af66fc99e Initial load
duke
parents:
diff changeset
419 // provide strong ST-ST order, so the issue is moot on IA32, x64, and SPARC.
a61af66fc99e Initial load
duke
parents:
diff changeset
420 //
a61af66fc99e Initial load
duke
parents:
diff changeset
421 // As a general policy we use "volatile" to control compiler-based reordering
a61af66fc99e Initial load
duke
parents:
diff changeset
422 // and explicit fences (barriers) to control for architectural reordering performed
a61af66fc99e Initial load
duke
parents:
diff changeset
423 // by the CPU(s) or platform.
a61af66fc99e Initial load
duke
parents:
diff changeset
424
a61af66fc99e Initial load
duke
parents:
diff changeset
425 static int MBFence (int x) { OrderAccess::fence(); return x; }
a61af66fc99e Initial load
duke
parents:
diff changeset
426
a61af66fc99e Initial load
duke
parents:
diff changeset
427 struct SharedGlobals {
a61af66fc99e Initial load
duke
parents:
diff changeset
428 // These are highly shared mostly-read variables.
a61af66fc99e Initial load
duke
parents:
diff changeset
429 // To avoid false-sharing they need to be the sole occupants of a $ line.
a61af66fc99e Initial load
duke
parents:
diff changeset
430 double padPrefix [8];
a61af66fc99e Initial load
duke
parents:
diff changeset
431 volatile int stwRandom ;
a61af66fc99e Initial load
duke
parents:
diff changeset
432 volatile int stwCycle ;
a61af66fc99e Initial load
duke
parents:
diff changeset
433
a61af66fc99e Initial load
duke
parents:
diff changeset
434 // Hot RW variables -- Sequester to avoid false-sharing
a61af66fc99e Initial load
duke
parents:
diff changeset
435 double padSuffix [16];
a61af66fc99e Initial load
duke
parents:
diff changeset
436 volatile int hcSequence ;
a61af66fc99e Initial load
duke
parents:
diff changeset
437 double padFinal [8] ;
a61af66fc99e Initial load
duke
parents:
diff changeset
438 } ;
a61af66fc99e Initial load
duke
parents:
diff changeset
439
a61af66fc99e Initial load
duke
parents:
diff changeset
440 static SharedGlobals GVars ;
1587
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
441 static int MonitorScavengeThreshold = 1000000 ;
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
442 static volatile int ForceMonitorScavenge = 0 ; // Scavenge required and pending
0
a61af66fc99e Initial load
duke
parents:
diff changeset
443
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
444 static markOop ReadStableMark (oop obj) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
445 markOop mark = obj->mark() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
446 if (!mark->is_being_inflated()) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
447 return mark ; // normal fast-path return
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
448 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
449
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
450 int its = 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
451 for (;;) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
452 markOop mark = obj->mark() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
453 if (!mark->is_being_inflated()) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
454 return mark ; // normal fast-path return
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
455 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
456
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
457 // The object is being inflated by some other thread.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
458 // The caller of ReadStableMark() must wait for inflation to complete.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
459 // Avoid live-lock
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
460 // TODO: consider calling SafepointSynchronize::do_call_back() while
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
461 // spinning to see if there's a safepoint pending. If so, immediately
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
462 // yielding or blocking would be appropriate. Avoid spinning while
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
463 // there is a safepoint pending.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
464 // TODO: add inflation contention performance counters.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
465 // TODO: restrict the aggregate number of spinners.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
466
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
467 ++its ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
468 if (its > 10000 || !os::is_MP()) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
469 if (its & 1) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
470 os::NakedYield() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
471 TEVENT (Inflate: INFLATING - yield) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
472 } else {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
473 // Note that the following code attenuates the livelock problem but is not
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
474 // a complete remedy. A more complete solution would require that the inflating
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
475 // thread hold the associated inflation lock. The following code simply restricts
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
476 // the number of spinners to at most one. We'll have N-2 threads blocked
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
477 // on the inflationlock, 1 thread holding the inflation lock and using
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
478 // a yield/park strategy, and 1 thread in the midst of inflation.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
479 // A more refined approach would be to change the encoding of INFLATING
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
480 // to allow encapsulation of a native thread pointer. Threads waiting for
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
481 // inflation to complete would use CAS to push themselves onto a singly linked
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
482 // list rooted at the markword. Once enqueued, they'd loop, checking a per-thread flag
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
483 // and calling park(). When inflation was complete the thread that accomplished inflation
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
484 // would detach the list and set the markword to inflated with a single CAS and
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
485 // then for each thread on the list, set the flag and unpark() the thread.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
486 // This is conceptually similar to muxAcquire-muxRelease, except that muxRelease
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
487 // wakes at most one thread whereas we need to wake the entire list.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
488 int ix = (intptr_t(obj) >> 5) & (NINFLATIONLOCKS-1) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
489 int YieldThenBlock = 0 ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
490 assert (ix >= 0 && ix < NINFLATIONLOCKS, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
491 assert ((NINFLATIONLOCKS & (NINFLATIONLOCKS-1)) == 0, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
492 Thread::muxAcquire (InflationLocks + ix, "InflationLock") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
493 while (obj->mark() == markOopDesc::INFLATING()) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
494 // Beware: NakedYield() is advisory and has almost no effect on some platforms
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
495 // so we periodically call Self->_ParkEvent->park(1).
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
496 // We use a mixed spin/yield/block mechanism.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
497 if ((YieldThenBlock++) >= 16) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
498 Thread::current()->_ParkEvent->park(1) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
499 } else {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
500 os::NakedYield() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
501 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
502 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
503 Thread::muxRelease (InflationLocks + ix ) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
504 TEVENT (Inflate: INFLATING - yield/park) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
505 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
506 } else {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
507 SpinPause() ; // SMP-polite spinning
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
508 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
509 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
510 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
511
a61af66fc99e Initial load
duke
parents:
diff changeset
512 // hashCode() generation :
a61af66fc99e Initial load
duke
parents:
diff changeset
513 //
a61af66fc99e Initial load
duke
parents:
diff changeset
514 // Possibilities:
a61af66fc99e Initial load
duke
parents:
diff changeset
515 // * MD5Digest of {obj,stwRandom}
a61af66fc99e Initial load
duke
parents:
diff changeset
516 // * CRC32 of {obj,stwRandom} or any linear-feedback shift register function.
a61af66fc99e Initial load
duke
parents:
diff changeset
517 // * A DES- or AES-style SBox[] mechanism
a61af66fc99e Initial load
duke
parents:
diff changeset
518 // * One of the Phi-based schemes, such as:
a61af66fc99e Initial load
duke
parents:
diff changeset
519 // 2654435761 = 2^32 * Phi (golden ratio)
a61af66fc99e Initial load
duke
parents:
diff changeset
520 // HashCodeValue = ((uintptr_t(obj) >> 3) * 2654435761) ^ GVars.stwRandom ;
a61af66fc99e Initial load
duke
parents:
diff changeset
521 // * A variation of Marsaglia's shift-xor RNG scheme.
a61af66fc99e Initial load
duke
parents:
diff changeset
522 // * (obj ^ stwRandom) is appealing, but can result
a61af66fc99e Initial load
duke
parents:
diff changeset
523 // in undesirable regularity in the hashCode values of adjacent objects
a61af66fc99e Initial load
duke
parents:
diff changeset
524 // (objects allocated back-to-back, in particular). This could potentially
a61af66fc99e Initial load
duke
parents:
diff changeset
525 // result in hashtable collisions and reduced hashtable efficiency.
a61af66fc99e Initial load
duke
parents:
diff changeset
526 // There are simple ways to "diffuse" the middle address bits over the
a61af66fc99e Initial load
duke
parents:
diff changeset
527 // generated hashCode values:
a61af66fc99e Initial load
duke
parents:
diff changeset
528 //
a61af66fc99e Initial load
duke
parents:
diff changeset
529
a61af66fc99e Initial load
duke
parents:
diff changeset
530 static inline intptr_t get_next_hash(Thread * Self, oop obj) {
a61af66fc99e Initial load
duke
parents:
diff changeset
531 intptr_t value = 0 ;
a61af66fc99e Initial load
duke
parents:
diff changeset
532 if (hashCode == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
533 // This form uses an unguarded global Park-Miller RNG,
a61af66fc99e Initial load
duke
parents:
diff changeset
534 // so it's possible for two threads to race and generate the same RNG.
a61af66fc99e Initial load
duke
parents:
diff changeset
535 // On MP system we'll have lots of RW access to a global, so the
a61af66fc99e Initial load
duke
parents:
diff changeset
536 // mechanism induces lots of coherency traffic.
a61af66fc99e Initial load
duke
parents:
diff changeset
537 value = os::random() ;
a61af66fc99e Initial load
duke
parents:
diff changeset
538 } else
a61af66fc99e Initial load
duke
parents:
diff changeset
539 if (hashCode == 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
540 // This variation has the property of being stable (idempotent)
a61af66fc99e Initial load
duke
parents:
diff changeset
541 // between STW operations. This can be useful in some of the 1-0
a61af66fc99e Initial load
duke
parents:
diff changeset
542 // synchronization schemes.
a61af66fc99e Initial load
duke
parents:
diff changeset
543 intptr_t addrBits = intptr_t(obj) >> 3 ;
a61af66fc99e Initial load
duke
parents:
diff changeset
544 value = addrBits ^ (addrBits >> 5) ^ GVars.stwRandom ;
a61af66fc99e Initial load
duke
parents:
diff changeset
545 } else
a61af66fc99e Initial load
duke
parents:
diff changeset
546 if (hashCode == 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
547 value = 1 ; // for sensitivity testing
a61af66fc99e Initial load
duke
parents:
diff changeset
548 } else
a61af66fc99e Initial load
duke
parents:
diff changeset
549 if (hashCode == 3) {
a61af66fc99e Initial load
duke
parents:
diff changeset
550 value = ++GVars.hcSequence ;
a61af66fc99e Initial load
duke
parents:
diff changeset
551 } else
a61af66fc99e Initial load
duke
parents:
diff changeset
552 if (hashCode == 4) {
a61af66fc99e Initial load
duke
parents:
diff changeset
553 value = intptr_t(obj) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
554 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
555 // Marsaglia's xor-shift scheme with thread-specific state
a61af66fc99e Initial load
duke
parents:
diff changeset
556 // This is probably the best overall implementation -- we'll
a61af66fc99e Initial load
duke
parents:
diff changeset
557 // likely make this the default in future releases.
a61af66fc99e Initial load
duke
parents:
diff changeset
558 unsigned t = Self->_hashStateX ;
a61af66fc99e Initial load
duke
parents:
diff changeset
559 t ^= (t << 11) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
560 Self->_hashStateX = Self->_hashStateY ;
a61af66fc99e Initial load
duke
parents:
diff changeset
561 Self->_hashStateY = Self->_hashStateZ ;
a61af66fc99e Initial load
duke
parents:
diff changeset
562 Self->_hashStateZ = Self->_hashStateW ;
a61af66fc99e Initial load
duke
parents:
diff changeset
563 unsigned v = Self->_hashStateW ;
a61af66fc99e Initial load
duke
parents:
diff changeset
564 v = (v ^ (v >> 19)) ^ (t ^ (t >> 8)) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
565 Self->_hashStateW = v ;
a61af66fc99e Initial load
duke
parents:
diff changeset
566 value = v ;
a61af66fc99e Initial load
duke
parents:
diff changeset
567 }
a61af66fc99e Initial load
duke
parents:
diff changeset
568
a61af66fc99e Initial load
duke
parents:
diff changeset
569 value &= markOopDesc::hash_mask;
a61af66fc99e Initial load
duke
parents:
diff changeset
570 if (value == 0) value = 0xBAD ;
a61af66fc99e Initial load
duke
parents:
diff changeset
571 assert (value != markOopDesc::no_hash, "invariant") ;
a61af66fc99e Initial load
duke
parents:
diff changeset
572 TEVENT (hashCode: GENERATE) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
573 return value;
a61af66fc99e Initial load
duke
parents:
diff changeset
574 }
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
575 //
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
576 intptr_t ObjectSynchronizer::FastHashCode (Thread * Self, oop obj) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
577 if (UseBiasedLocking) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
578 // NOTE: many places throughout the JVM do not expect a safepoint
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
579 // to be taken here, in particular most operations on perm gen
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
580 // objects. However, we only ever bias Java instances and all of
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
581 // the call sites of identity_hash that might revoke biases have
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
582 // been checked to make sure they can handle a safepoint. The
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
583 // added check of the bias pattern is to avoid useless calls to
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
584 // thread-local storage.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
585 if (obj->mark()->has_bias_pattern()) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
586 // Box and unbox the raw reference just in case we cause a STW safepoint.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
587 Handle hobj (Self, obj) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
588 // Relaxing assertion for bug 6320749.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
589 assert (Universe::verify_in_progress() ||
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
590 !SafepointSynchronize::is_at_safepoint(),
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
591 "biases should not be seen by VM thread here");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
592 BiasedLocking::revoke_and_rebias(hobj, false, JavaThread::current());
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
593 obj = hobj() ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
594 assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
595 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
596 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
597
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
598 // hashCode() is a heap mutator ...
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
599 // Relaxing assertion for bug 6320749.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
600 assert (Universe::verify_in_progress() ||
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
601 !SafepointSynchronize::is_at_safepoint(), "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
602 assert (Universe::verify_in_progress() ||
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
603 Self->is_Java_thread() , "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
604 assert (Universe::verify_in_progress() ||
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
605 ((JavaThread *)Self)->thread_state() != _thread_blocked, "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
606
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
607 ObjectMonitor* monitor = NULL;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
608 markOop temp, test;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
609 intptr_t hash;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
610 markOop mark = ReadStableMark (obj);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
611
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
612 // object should remain ineligible for biased locking
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
613 assert (!mark->has_bias_pattern(), "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
614
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
615 if (mark->is_neutral()) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
616 hash = mark->hash(); // this is a normal header
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
617 if (hash) { // if it has hash, just return it
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
618 return hash;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
619 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
620 hash = get_next_hash(Self, obj); // allocate a new hash code
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
621 temp = mark->copy_set_hash(hash); // merge the hash code into header
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
622 // use (machine word version) atomic operation to install the hash
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
623 test = (markOop) Atomic::cmpxchg_ptr(temp, obj->mark_addr(), mark);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
624 if (test == mark) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
625 return hash;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
626 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
627 // If atomic operation failed, we must inflate the header
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
628 // into heavy weight monitor. We could add more code here
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
629 // for fast path, but it does not worth the complexity.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
630 } else if (mark->has_monitor()) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
631 monitor = mark->monitor();
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
632 temp = monitor->header();
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
633 assert (temp->is_neutral(), "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
634 hash = temp->hash();
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
635 if (hash) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
636 return hash;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
637 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
638 // Skip to the following code to reduce code size
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
639 } else if (Self->is_lock_owned((address)mark->locker())) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
640 temp = mark->displaced_mark_helper(); // this is a lightweight monitor owned
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
641 assert (temp->is_neutral(), "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
642 hash = temp->hash(); // by current thread, check if the displaced
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
643 if (hash) { // header contains hash code
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
644 return hash;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
645 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
646 // WARNING:
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
647 // The displaced header is strictly immutable.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
648 // It can NOT be changed in ANY cases. So we have
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
649 // to inflate the header into heavyweight monitor
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
650 // even the current thread owns the lock. The reason
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
651 // is the BasicLock (stack slot) will be asynchronously
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
652 // read by other threads during the inflate() function.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
653 // Any change to stack may not propagate to other threads
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
654 // correctly.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
655 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
656
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
657 // Inflate the monitor to set hash code
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
658 monitor = ObjectSynchronizer::inflate(Self, obj);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
659 // Load displaced header and check it has hash code
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
660 mark = monitor->header();
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
661 assert (mark->is_neutral(), "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
662 hash = mark->hash();
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
663 if (hash == 0) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
664 hash = get_next_hash(Self, obj);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
665 temp = mark->copy_set_hash(hash); // merge hash code into header
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
666 assert (temp->is_neutral(), "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
667 test = (markOop) Atomic::cmpxchg_ptr(temp, monitor, mark);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
668 if (test != mark) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
669 // The only update to the header in the monitor (outside GC)
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
670 // is install the hash code. If someone add new usage of
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
671 // displaced header, please update this code
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
672 hash = test->hash();
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
673 assert (test->is_neutral(), "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
674 assert (hash != 0, "Trivial unexpected object/monitor header usage.");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
675 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
676 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
677 // We finally get the hash
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
678 return hash;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
679 }
a61af66fc99e Initial load
duke
parents:
diff changeset
680
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
681 // Deprecated -- use FastHashCode() instead.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
682
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
683 intptr_t ObjectSynchronizer::identity_hash_value_for(Handle obj) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
684 return FastHashCode (Thread::current(), obj()) ;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
685 }
a61af66fc99e Initial load
duke
parents:
diff changeset
686
a61af66fc99e Initial load
duke
parents:
diff changeset
687
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
688 bool ObjectSynchronizer::current_thread_holds_lock(JavaThread* thread,
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
689 Handle h_obj) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
690 if (UseBiasedLocking) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
691 BiasedLocking::revoke_and_rebias(h_obj, false, thread);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
692 assert(!h_obj->mark()->has_bias_pattern(), "biases should be revoked by now");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
693 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
694
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
695 assert(thread == JavaThread::current(), "Can only be called on current thread");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
696 oop obj = h_obj();
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
697
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
698 markOop mark = ReadStableMark (obj) ;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
699
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
700 // Uncontended case, header points to stack
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
701 if (mark->has_locker()) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
702 return thread->is_lock_owned((address)mark->locker());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
703 }
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
704 // Contended case, header points to ObjectMonitor (tagged pointer)
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
705 if (mark->has_monitor()) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
706 ObjectMonitor* monitor = mark->monitor();
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
707 return monitor->is_entered(thread) != 0 ;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
708 }
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
709 // Unlocked case, header in place
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
710 assert(mark->is_neutral(), "sanity check");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
711 return false;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
712 }
a61af66fc99e Initial load
duke
parents:
diff changeset
713
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
714 // Be aware of this method could revoke bias of the lock object.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
715 // This method querys the ownership of the lock handle specified by 'h_obj'.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
716 // If the current thread owns the lock, it returns owner_self. If no
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
717 // thread owns the lock, it returns owner_none. Otherwise, it will return
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
718 // ower_other.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
719 ObjectSynchronizer::LockOwnership ObjectSynchronizer::query_lock_ownership
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
720 (JavaThread *self, Handle h_obj) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
721 // The caller must beware this method can revoke bias, and
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
722 // revocation can result in a safepoint.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
723 assert (!SafepointSynchronize::is_at_safepoint(), "invariant") ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
724 assert (self->thread_state() != _thread_blocked , "invariant") ;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
725
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
726 // Possible mark states: neutral, biased, stack-locked, inflated
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
727
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
728 if (UseBiasedLocking && h_obj()->mark()->has_bias_pattern()) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
729 // CASE: biased
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
730 BiasedLocking::revoke_and_rebias(h_obj, false, self);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
731 assert(!h_obj->mark()->has_bias_pattern(),
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
732 "biases should be revoked by now");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
733 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
734
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
735 assert(self == JavaThread::current(), "Can only be called on current thread");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
736 oop obj = h_obj();
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
737 markOop mark = ReadStableMark (obj) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
738
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
739 // CASE: stack-locked. Mark points to a BasicLock on the owner's stack.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
740 if (mark->has_locker()) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
741 return self->is_lock_owned((address)mark->locker()) ?
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
742 owner_self : owner_other;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
743 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
744
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
745 // CASE: inflated. Mark (tagged pointer) points to an objectMonitor.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
746 // The Object:ObjectMonitor relationship is stable as long as we're
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
747 // not at a safepoint.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
748 if (mark->has_monitor()) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
749 void * owner = mark->monitor()->_owner ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
750 if (owner == NULL) return owner_none ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
751 return (owner == self ||
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
752 self->is_lock_owned((address)owner)) ? owner_self : owner_other;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
753 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
754
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
755 // CASE: neutral
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
756 assert(mark->is_neutral(), "sanity check");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
757 return owner_none ; // it's unlocked
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
758 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
759
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
760 // FIXME: jvmti should call this
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
761 JavaThread* ObjectSynchronizer::get_lock_owner(Handle h_obj, bool doLock) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
762 if (UseBiasedLocking) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
763 if (SafepointSynchronize::is_at_safepoint()) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
764 BiasedLocking::revoke_at_safepoint(h_obj);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
765 } else {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
766 BiasedLocking::revoke_and_rebias(h_obj, false, JavaThread::current());
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
767 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
768 assert(!h_obj->mark()->has_bias_pattern(), "biases should be revoked by now");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
769 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
770
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
771 oop obj = h_obj();
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
772 address owner = NULL;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
773
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
774 markOop mark = ReadStableMark (obj) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
775
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
776 // Uncontended case, header points to stack
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
777 if (mark->has_locker()) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
778 owner = (address) mark->locker();
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
779 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
780
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
781 // Contended case, header points to ObjectMonitor (tagged pointer)
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
782 if (mark->has_monitor()) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
783 ObjectMonitor* monitor = mark->monitor();
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
784 assert(monitor != NULL, "monitor should be non-null");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
785 owner = (address) monitor->owner();
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
786 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
787
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
788 if (owner != NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
789 return Threads::owning_thread_from_monitor_owner(owner, doLock);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
790 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
791
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
792 // Unlocked case, header in place
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
793 // Cannot have assertion since this object may have been
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
794 // locked by another thread when reaching here.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
795 // assert(mark->is_neutral(), "sanity check");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
796
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
797 return NULL;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
798 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
799 // Visitors ...
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
800
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
801 void ObjectSynchronizer::monitors_iterate(MonitorClosure* closure) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
802 ObjectMonitor* block = gBlockList;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
803 ObjectMonitor* mid;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
804 while (block) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
805 assert(block->object() == CHAINMARKER, "must be a block header");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
806 for (int i = _BLOCKSIZE - 1; i > 0; i--) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
807 mid = block + i;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
808 oop object = (oop) mid->object();
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
809 if (object != NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
810 closure->do_monitor(mid);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
811 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
812 }
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
813 block = (ObjectMonitor*) block->FreeNext;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
814 }
a61af66fc99e Initial load
duke
parents:
diff changeset
815 }
a61af66fc99e Initial load
duke
parents:
diff changeset
816
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
817 // Get the next block in the block list.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
818 static inline ObjectMonitor* next(ObjectMonitor* block) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
819 assert(block->object() == CHAINMARKER, "must be a block header");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
820 block = block->FreeNext ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
821 assert(block == NULL || block->object() == CHAINMARKER, "must be a block header");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
822 return block;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
823 }
a61af66fc99e Initial load
duke
parents:
diff changeset
824
a61af66fc99e Initial load
duke
parents:
diff changeset
825
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
826 void ObjectSynchronizer::oops_do(OopClosure* f) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
827 assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
828 for (ObjectMonitor* block = gBlockList; block != NULL; block = next(block)) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
829 assert(block->object() == CHAINMARKER, "must be a block header");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
830 for (int i = 1; i < _BLOCKSIZE; i++) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
831 ObjectMonitor* mid = &block[i];
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
832 if (mid->object() != NULL) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
833 f->do_oop((oop*)mid->object_addr());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
834 }
a61af66fc99e Initial load
duke
parents:
diff changeset
835 }
a61af66fc99e Initial load
duke
parents:
diff changeset
836 }
a61af66fc99e Initial load
duke
parents:
diff changeset
837 }
a61af66fc99e Initial load
duke
parents:
diff changeset
838
a61af66fc99e Initial load
duke
parents:
diff changeset
839
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
840 // -----------------------------------------------------------------------------
0
a61af66fc99e Initial load
duke
parents:
diff changeset
841 // ObjectMonitor Lifecycle
a61af66fc99e Initial load
duke
parents:
diff changeset
842 // -----------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
843 // Inflation unlinks monitors from the global gFreeList and
a61af66fc99e Initial load
duke
parents:
diff changeset
844 // associates them with objects. Deflation -- which occurs at
a61af66fc99e Initial load
duke
parents:
diff changeset
845 // STW-time -- disassociates idle monitors from objects. Such
a61af66fc99e Initial load
duke
parents:
diff changeset
846 // scavenged monitors are returned to the gFreeList.
a61af66fc99e Initial load
duke
parents:
diff changeset
847 //
a61af66fc99e Initial load
duke
parents:
diff changeset
848 // The global list is protected by ListLock. All the critical sections
a61af66fc99e Initial load
duke
parents:
diff changeset
849 // are short and operate in constant-time.
a61af66fc99e Initial load
duke
parents:
diff changeset
850 //
a61af66fc99e Initial load
duke
parents:
diff changeset
851 // ObjectMonitors reside in type-stable memory (TSM) and are immortal.
a61af66fc99e Initial load
duke
parents:
diff changeset
852 //
a61af66fc99e Initial load
duke
parents:
diff changeset
853 // Lifecycle:
a61af66fc99e Initial load
duke
parents:
diff changeset
854 // -- unassigned and on the global free list
a61af66fc99e Initial load
duke
parents:
diff changeset
855 // -- unassigned and on a thread's private omFreeList
a61af66fc99e Initial load
duke
parents:
diff changeset
856 // -- assigned to an object. The object is inflated and the mark refers
a61af66fc99e Initial load
duke
parents:
diff changeset
857 // to the objectmonitor.
a61af66fc99e Initial load
duke
parents:
diff changeset
858 //
a61af66fc99e Initial load
duke
parents:
diff changeset
859
a61af66fc99e Initial load
duke
parents:
diff changeset
860
1587
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
861 // Constraining monitor pool growth via MonitorBound ...
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
862 //
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
863 // The monitor pool is grow-only. We scavenge at STW safepoint-time, but the
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
864 // the rate of scavenging is driven primarily by GC. As such, we can find
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
865 // an inordinate number of monitors in circulation.
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
866 // To avoid that scenario we can artificially induce a STW safepoint
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
867 // if the pool appears to be growing past some reasonable bound.
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
868 // Generally we favor time in space-time tradeoffs, but as there's no
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
869 // natural back-pressure on the # of extant monitors we need to impose some
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
870 // type of limit. Beware that if MonitorBound is set to too low a value
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
871 // we could just loop. In addition, if MonitorBound is set to a low value
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
872 // we'll incur more safepoints, which are harmful to performance.
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
873 // See also: GuaranteedSafepointInterval
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
874 //
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
875 // The current implementation uses asynchronous VM operations.
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
876 //
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
877
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
878 static void InduceScavenge (Thread * Self, const char * Whence) {
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
879 // Induce STW safepoint to trim monitors
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
880 // Ultimately, this results in a call to deflate_idle_monitors() in the near future.
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
881 // More precisely, trigger an asynchronous STW safepoint as the number
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
882 // of active monitors passes the specified threshold.
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
883 // TODO: assert thread state is reasonable
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
884
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
885 if (ForceMonitorScavenge == 0 && Atomic::xchg (1, &ForceMonitorScavenge) == 0) {
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
886 if (ObjectMonitor::Knob_Verbose) {
1587
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
887 ::printf ("Monitor scavenge - Induced STW @%s (%d)\n", Whence, ForceMonitorScavenge) ;
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
888 ::fflush(stdout) ;
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
889 }
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
890 // Induce a 'null' safepoint to scavenge monitors
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
891 // Must VM_Operation instance be heap allocated as the op will be enqueue and posted
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
892 // to the VMthread and have a lifespan longer than that of this activation record.
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
893 // The VMThread will delete the op when completed.
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
894 VMThread::execute (new VM_ForceAsyncSafepoint()) ;
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
895
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
896 if (ObjectMonitor::Knob_Verbose) {
1587
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
897 ::printf ("Monitor scavenge - STW posted @%s (%d)\n", Whence, ForceMonitorScavenge) ;
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
898 ::fflush(stdout) ;
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
899 }
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
900 }
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
901 }
1640
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
902 /* Too slow for general assert or debug
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
903 void ObjectSynchronizer::verifyInUse (Thread *Self) {
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
904 ObjectMonitor* mid;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
905 int inusetally = 0;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
906 for (mid = Self->omInUseList; mid != NULL; mid = mid->FreeNext) {
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
907 inusetally ++;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
908 }
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
909 assert(inusetally == Self->omInUseCount, "inuse count off");
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
910
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
911 int freetally = 0;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
912 for (mid = Self->omFreeList; mid != NULL; mid = mid->FreeNext) {
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
913 freetally ++;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
914 }
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
915 assert(freetally == Self->omFreeCount, "free count off");
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
916 }
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
917 */
0
a61af66fc99e Initial load
duke
parents:
diff changeset
918 ObjectMonitor * ATTR ObjectSynchronizer::omAlloc (Thread * Self) {
a61af66fc99e Initial load
duke
parents:
diff changeset
919 // A large MAXPRIVATE value reduces both list lock contention
a61af66fc99e Initial load
duke
parents:
diff changeset
920 // and list coherency traffic, but also tends to increase the
a61af66fc99e Initial load
duke
parents:
diff changeset
921 // number of objectMonitors in circulation as well as the STW
a61af66fc99e Initial load
duke
parents:
diff changeset
922 // scavenge costs. As usual, we lean toward time in space-time
a61af66fc99e Initial load
duke
parents:
diff changeset
923 // tradeoffs.
a61af66fc99e Initial load
duke
parents:
diff changeset
924 const int MAXPRIVATE = 1024 ;
a61af66fc99e Initial load
duke
parents:
diff changeset
925 for (;;) {
a61af66fc99e Initial load
duke
parents:
diff changeset
926 ObjectMonitor * m ;
a61af66fc99e Initial load
duke
parents:
diff changeset
927
a61af66fc99e Initial load
duke
parents:
diff changeset
928 // 1: try to allocate from the thread's local omFreeList.
a61af66fc99e Initial load
duke
parents:
diff changeset
929 // Threads will attempt to allocate first from their local list, then
a61af66fc99e Initial load
duke
parents:
diff changeset
930 // from the global list, and only after those attempts fail will the thread
a61af66fc99e Initial load
duke
parents:
diff changeset
931 // attempt to instantiate new monitors. Thread-local free lists take
a61af66fc99e Initial load
duke
parents:
diff changeset
932 // heat off the ListLock and improve allocation latency, as well as reducing
a61af66fc99e Initial load
duke
parents:
diff changeset
933 // coherency traffic on the shared global list.
a61af66fc99e Initial load
duke
parents:
diff changeset
934 m = Self->omFreeList ;
a61af66fc99e Initial load
duke
parents:
diff changeset
935 if (m != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
936 Self->omFreeList = m->FreeNext ;
a61af66fc99e Initial load
duke
parents:
diff changeset
937 Self->omFreeCount -- ;
a61af66fc99e Initial load
duke
parents:
diff changeset
938 // CONSIDER: set m->FreeNext = BAD -- diagnostic hygiene
a61af66fc99e Initial load
duke
parents:
diff changeset
939 guarantee (m->object() == NULL, "invariant") ;
1587
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
940 if (MonitorInUseLists) {
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
941 m->FreeNext = Self->omInUseList;
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
942 Self->omInUseList = m;
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
943 Self->omInUseCount ++;
1640
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
944 // verifyInUse(Self);
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
945 } else {
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
946 m->FreeNext = NULL;
1587
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
947 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
948 return m ;
a61af66fc99e Initial load
duke
parents:
diff changeset
949 }
a61af66fc99e Initial load
duke
parents:
diff changeset
950
a61af66fc99e Initial load
duke
parents:
diff changeset
951 // 2: try to allocate from the global gFreeList
a61af66fc99e Initial load
duke
parents:
diff changeset
952 // CONSIDER: use muxTry() instead of muxAcquire().
a61af66fc99e Initial load
duke
parents:
diff changeset
953 // If the muxTry() fails then drop immediately into case 3.
a61af66fc99e Initial load
duke
parents:
diff changeset
954 // If we're using thread-local free lists then try
a61af66fc99e Initial load
duke
parents:
diff changeset
955 // to reprovision the caller's free list.
a61af66fc99e Initial load
duke
parents:
diff changeset
956 if (gFreeList != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
957 // Reprovision the thread's omFreeList.
a61af66fc99e Initial load
duke
parents:
diff changeset
958 // Use bulk transfers to reduce the allocation rate and heat
a61af66fc99e Initial load
duke
parents:
diff changeset
959 // on various locks.
a61af66fc99e Initial load
duke
parents:
diff changeset
960 Thread::muxAcquire (&ListLock, "omAlloc") ;
a61af66fc99e Initial load
duke
parents:
diff changeset
961 for (int i = Self->omFreeProvision; --i >= 0 && gFreeList != NULL; ) {
1587
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
962 MonitorFreeCount --;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
963 ObjectMonitor * take = gFreeList ;
a61af66fc99e Initial load
duke
parents:
diff changeset
964 gFreeList = take->FreeNext ;
a61af66fc99e Initial load
duke
parents:
diff changeset
965 guarantee (take->object() == NULL, "invariant") ;
a61af66fc99e Initial load
duke
parents:
diff changeset
966 guarantee (!take->is_busy(), "invariant") ;
a61af66fc99e Initial load
duke
parents:
diff changeset
967 take->Recycle() ;
1640
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
968 omRelease (Self, take, false) ;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
969 }
a61af66fc99e Initial load
duke
parents:
diff changeset
970 Thread::muxRelease (&ListLock) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
971 Self->omFreeProvision += 1 + (Self->omFreeProvision/2) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
972 if (Self->omFreeProvision > MAXPRIVATE ) Self->omFreeProvision = MAXPRIVATE ;
a61af66fc99e Initial load
duke
parents:
diff changeset
973 TEVENT (omFirst - reprovision) ;
1587
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
974
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
975 const int mx = MonitorBound ;
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
976 if (mx > 0 && (MonitorPopulation-MonitorFreeCount) > mx) {
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
977 // We can't safely induce a STW safepoint from omAlloc() as our thread
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
978 // state may not be appropriate for such activities and callers may hold
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
979 // naked oops, so instead we defer the action.
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
980 InduceScavenge (Self, "omAlloc") ;
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
981 }
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
982 continue;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
983 }
a61af66fc99e Initial load
duke
parents:
diff changeset
984
a61af66fc99e Initial load
duke
parents:
diff changeset
985 // 3: allocate a block of new ObjectMonitors
a61af66fc99e Initial load
duke
parents:
diff changeset
986 // Both the local and global free lists are empty -- resort to malloc().
a61af66fc99e Initial load
duke
parents:
diff changeset
987 // In the current implementation objectMonitors are TSM - immortal.
a61af66fc99e Initial load
duke
parents:
diff changeset
988 assert (_BLOCKSIZE > 1, "invariant") ;
a61af66fc99e Initial load
duke
parents:
diff changeset
989 ObjectMonitor * temp = new ObjectMonitor[_BLOCKSIZE];
a61af66fc99e Initial load
duke
parents:
diff changeset
990
a61af66fc99e Initial load
duke
parents:
diff changeset
991 // NOTE: (almost) no way to recover if allocation failed.
a61af66fc99e Initial load
duke
parents:
diff changeset
992 // We might be able to induce a STW safepoint and scavenge enough
a61af66fc99e Initial load
duke
parents:
diff changeset
993 // objectMonitors to permit progress.
a61af66fc99e Initial load
duke
parents:
diff changeset
994 if (temp == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
995 vm_exit_out_of_memory (sizeof (ObjectMonitor[_BLOCKSIZE]), "Allocate ObjectMonitors") ;
a61af66fc99e Initial load
duke
parents:
diff changeset
996 }
a61af66fc99e Initial load
duke
parents:
diff changeset
997
a61af66fc99e Initial load
duke
parents:
diff changeset
998 // Format the block.
a61af66fc99e Initial load
duke
parents:
diff changeset
999 // initialize the linked list, each monitor points to its next
a61af66fc99e Initial load
duke
parents:
diff changeset
1000 // forming the single linked free list, the very first monitor
a61af66fc99e Initial load
duke
parents:
diff changeset
1001 // will points to next block, which forms the block list.
a61af66fc99e Initial load
duke
parents:
diff changeset
1002 // The trick of using the 1st element in the block as gBlockList
a61af66fc99e Initial load
duke
parents:
diff changeset
1003 // linkage should be reconsidered. A better implementation would
a61af66fc99e Initial load
duke
parents:
diff changeset
1004 // look like: class Block { Block * next; int N; ObjectMonitor Body [N] ; }
a61af66fc99e Initial load
duke
parents:
diff changeset
1005
a61af66fc99e Initial load
duke
parents:
diff changeset
1006 for (int i = 1; i < _BLOCKSIZE ; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1007 temp[i].FreeNext = &temp[i+1];
a61af66fc99e Initial load
duke
parents:
diff changeset
1008 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1009
a61af66fc99e Initial load
duke
parents:
diff changeset
1010 // terminate the last monitor as the end of list
a61af66fc99e Initial load
duke
parents:
diff changeset
1011 temp[_BLOCKSIZE - 1].FreeNext = NULL ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1012
a61af66fc99e Initial load
duke
parents:
diff changeset
1013 // Element [0] is reserved for global list linkage
a61af66fc99e Initial load
duke
parents:
diff changeset
1014 temp[0].set_object(CHAINMARKER);
a61af66fc99e Initial load
duke
parents:
diff changeset
1015
a61af66fc99e Initial load
duke
parents:
diff changeset
1016 // Consider carving out this thread's current request from the
a61af66fc99e Initial load
duke
parents:
diff changeset
1017 // block in hand. This avoids some lock traffic and redundant
a61af66fc99e Initial load
duke
parents:
diff changeset
1018 // list activity.
a61af66fc99e Initial load
duke
parents:
diff changeset
1019
a61af66fc99e Initial load
duke
parents:
diff changeset
1020 // Acquire the ListLock to manipulate BlockList and FreeList.
a61af66fc99e Initial load
duke
parents:
diff changeset
1021 // An Oyama-Taura-Yonezawa scheme might be more efficient.
a61af66fc99e Initial load
duke
parents:
diff changeset
1022 Thread::muxAcquire (&ListLock, "omAlloc [2]") ;
1587
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1023 MonitorPopulation += _BLOCKSIZE-1;
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1024 MonitorFreeCount += _BLOCKSIZE-1;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1025
a61af66fc99e Initial load
duke
parents:
diff changeset
1026 // Add the new block to the list of extant blocks (gBlockList).
a61af66fc99e Initial load
duke
parents:
diff changeset
1027 // The very first objectMonitor in a block is reserved and dedicated.
a61af66fc99e Initial load
duke
parents:
diff changeset
1028 // It serves as blocklist "next" linkage.
a61af66fc99e Initial load
duke
parents:
diff changeset
1029 temp[0].FreeNext = gBlockList;
a61af66fc99e Initial load
duke
parents:
diff changeset
1030 gBlockList = temp;
a61af66fc99e Initial load
duke
parents:
diff changeset
1031
a61af66fc99e Initial load
duke
parents:
diff changeset
1032 // Add the new string of objectMonitors to the global free list
a61af66fc99e Initial load
duke
parents:
diff changeset
1033 temp[_BLOCKSIZE - 1].FreeNext = gFreeList ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1034 gFreeList = temp + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
1035 Thread::muxRelease (&ListLock) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1036 TEVENT (Allocate block of monitors) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1037 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1038 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1039
a61af66fc99e Initial load
duke
parents:
diff changeset
1040 // Place "m" on the caller's private per-thread omFreeList.
a61af66fc99e Initial load
duke
parents:
diff changeset
1041 // In practice there's no need to clamp or limit the number of
a61af66fc99e Initial load
duke
parents:
diff changeset
1042 // monitors on a thread's omFreeList as the only time we'll call
a61af66fc99e Initial load
duke
parents:
diff changeset
1043 // omRelease is to return a monitor to the free list after a CAS
a61af66fc99e Initial load
duke
parents:
diff changeset
1044 // attempt failed. This doesn't allow unbounded #s of monitors to
a61af66fc99e Initial load
duke
parents:
diff changeset
1045 // accumulate on a thread's free list.
a61af66fc99e Initial load
duke
parents:
diff changeset
1046 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1047
1640
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1048 void ObjectSynchronizer::omRelease (Thread * Self, ObjectMonitor * m, bool fromPerThreadAlloc) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1049 guarantee (m->object() == NULL, "invariant") ;
1640
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1050
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1051 // Remove from omInUseList
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1052 if (MonitorInUseLists && fromPerThreadAlloc) {
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1053 ObjectMonitor* curmidinuse = NULL;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1054 for (ObjectMonitor* mid = Self->omInUseList; mid != NULL; ) {
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1055 if (m == mid) {
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1056 // extract from per-thread in-use-list
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1057 if (mid == Self->omInUseList) {
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1058 Self->omInUseList = mid->FreeNext;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1059 } else if (curmidinuse != NULL) {
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1060 curmidinuse->FreeNext = mid->FreeNext; // maintain the current thread inuselist
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1061 }
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1062 Self->omInUseCount --;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1063 // verifyInUse(Self);
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1064 break;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1065 } else {
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1066 curmidinuse = mid;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1067 mid = mid->FreeNext;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1068 }
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1069 }
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1070 }
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1071
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1072 // FreeNext is used for both onInUseList and omFreeList, so clear old before setting new
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1073 m->FreeNext = Self->omFreeList ;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1074 Self->omFreeList = m ;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1075 Self->omFreeCount ++ ;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1076 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1077
a61af66fc99e Initial load
duke
parents:
diff changeset
1078 // Return the monitors of a moribund thread's local free list to
a61af66fc99e Initial load
duke
parents:
diff changeset
1079 // the global free list. Typically a thread calls omFlush() when
a61af66fc99e Initial load
duke
parents:
diff changeset
1080 // it's dying. We could also consider having the VM thread steal
a61af66fc99e Initial load
duke
parents:
diff changeset
1081 // monitors from threads that have not run java code over a few
a61af66fc99e Initial load
duke
parents:
diff changeset
1082 // consecutive STW safepoints. Relatedly, we might decay
a61af66fc99e Initial load
duke
parents:
diff changeset
1083 // omFreeProvision at STW safepoints.
a61af66fc99e Initial load
duke
parents:
diff changeset
1084 //
1640
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1085 // Also return the monitors of a moribund thread"s omInUseList to
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1086 // a global gOmInUseList under the global list lock so these
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1087 // will continue to be scanned.
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1088 //
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1089 // We currently call omFlush() from the Thread:: dtor _after the thread
a61af66fc99e Initial load
duke
parents:
diff changeset
1090 // has been excised from the thread list and is no longer a mutator.
a61af66fc99e Initial load
duke
parents:
diff changeset
1091 // That means that omFlush() can run concurrently with a safepoint and
a61af66fc99e Initial load
duke
parents:
diff changeset
1092 // the scavenge operator. Calling omFlush() from JavaThread::exit() might
a61af66fc99e Initial load
duke
parents:
diff changeset
1093 // be a better choice as we could safely reason that that the JVM is
a61af66fc99e Initial load
duke
parents:
diff changeset
1094 // not at a safepoint at the time of the call, and thus there could
a61af66fc99e Initial load
duke
parents:
diff changeset
1095 // be not inopportune interleavings between omFlush() and the scavenge
a61af66fc99e Initial load
duke
parents:
diff changeset
1096 // operator.
a61af66fc99e Initial load
duke
parents:
diff changeset
1097
a61af66fc99e Initial load
duke
parents:
diff changeset
1098 void ObjectSynchronizer::omFlush (Thread * Self) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1099 ObjectMonitor * List = Self->omFreeList ; // Null-terminated SLL
a61af66fc99e Initial load
duke
parents:
diff changeset
1100 Self->omFreeList = NULL ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1101 ObjectMonitor * Tail = NULL ;
1587
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1102 int Tally = 0;
1640
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1103 if (List != NULL) {
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1104 ObjectMonitor * s ;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1105 for (s = List ; s != NULL ; s = s->FreeNext) {
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1106 Tally ++ ;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1107 Tail = s ;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1108 guarantee (s->object() == NULL, "invariant") ;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1109 guarantee (!s->is_busy(), "invariant") ;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1110 s->set_owner (NULL) ; // redundant but good hygiene
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1111 TEVENT (omFlush - Move one) ;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1112 }
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1113 guarantee (Tail != NULL && List != NULL, "invariant") ;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1114 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1115
1640
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1116 ObjectMonitor * InUseList = Self->omInUseList;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1117 ObjectMonitor * InUseTail = NULL ;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1118 int InUseTally = 0;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1119 if (InUseList != NULL) {
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1120 Self->omInUseList = NULL;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1121 ObjectMonitor *curom;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1122 for (curom = InUseList; curom != NULL; curom = curom->FreeNext) {
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1123 InUseTail = curom;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1124 InUseTally++;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1125 }
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1126 // TODO debug
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1127 assert(Self->omInUseCount == InUseTally, "inuse count off");
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1128 Self->omInUseCount = 0;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1129 guarantee (InUseTail != NULL && InUseList != NULL, "invariant");
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1130 }
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1131
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1132 Thread::muxAcquire (&ListLock, "omFlush") ;
1640
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1133 if (Tail != NULL) {
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1134 Tail->FreeNext = gFreeList ;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1135 gFreeList = List ;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1136 MonitorFreeCount += Tally;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1137 }
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1138
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1139 if (InUseTail != NULL) {
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1140 InUseTail->FreeNext = gOmInUseList;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1141 gOmInUseList = InUseList;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1142 gOmInUseCount += InUseTally;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1143 }
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1144
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1145 Thread::muxRelease (&ListLock) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1146 TEVENT (omFlush) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1147 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1148
a61af66fc99e Initial load
duke
parents:
diff changeset
1149 // Fast path code shared by multiple functions
a61af66fc99e Initial load
duke
parents:
diff changeset
1150 ObjectMonitor* ObjectSynchronizer::inflate_helper(oop obj) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1151 markOop mark = obj->mark();
a61af66fc99e Initial load
duke
parents:
diff changeset
1152 if (mark->has_monitor()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1153 assert(ObjectSynchronizer::verify_objmon_isinpool(mark->monitor()), "monitor is invalid");
a61af66fc99e Initial load
duke
parents:
diff changeset
1154 assert(mark->monitor()->header()->is_neutral(), "monitor must record a good object header");
a61af66fc99e Initial load
duke
parents:
diff changeset
1155 return mark->monitor();
a61af66fc99e Initial load
duke
parents:
diff changeset
1156 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1157 return ObjectSynchronizer::inflate(Thread::current(), obj);
a61af66fc99e Initial load
duke
parents:
diff changeset
1158 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1159
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1160
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1161 // Note that we could encounter some performance loss through false-sharing as
a61af66fc99e Initial load
duke
parents:
diff changeset
1162 // multiple locks occupy the same $ line. Padding might be appropriate.
a61af66fc99e Initial load
duke
parents:
diff changeset
1163
a61af66fc99e Initial load
duke
parents:
diff changeset
1164
a61af66fc99e Initial load
duke
parents:
diff changeset
1165 ObjectMonitor * ATTR ObjectSynchronizer::inflate (Thread * Self, oop object) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1166 // Inflate mutates the heap ...
a61af66fc99e Initial load
duke
parents:
diff changeset
1167 // Relaxing assertion for bug 6320749.
a61af66fc99e Initial load
duke
parents:
diff changeset
1168 assert (Universe::verify_in_progress() ||
a61af66fc99e Initial load
duke
parents:
diff changeset
1169 !SafepointSynchronize::is_at_safepoint(), "invariant") ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1170
a61af66fc99e Initial load
duke
parents:
diff changeset
1171 for (;;) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1172 const markOop mark = object->mark() ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1173 assert (!mark->has_bias_pattern(), "invariant") ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1174
a61af66fc99e Initial load
duke
parents:
diff changeset
1175 // The mark can be in one of the following states:
a61af66fc99e Initial load
duke
parents:
diff changeset
1176 // * Inflated - just return
a61af66fc99e Initial load
duke
parents:
diff changeset
1177 // * Stack-locked - coerce it to inflated
a61af66fc99e Initial load
duke
parents:
diff changeset
1178 // * INFLATING - busy wait for conversion to complete
a61af66fc99e Initial load
duke
parents:
diff changeset
1179 // * Neutral - aggressively inflate the object.
a61af66fc99e Initial load
duke
parents:
diff changeset
1180 // * BIASED - Illegal. We should never see this
a61af66fc99e Initial load
duke
parents:
diff changeset
1181
a61af66fc99e Initial load
duke
parents:
diff changeset
1182 // CASE: inflated
a61af66fc99e Initial load
duke
parents:
diff changeset
1183 if (mark->has_monitor()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1184 ObjectMonitor * inf = mark->monitor() ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1185 assert (inf->header()->is_neutral(), "invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
1186 assert (inf->object() == object, "invariant") ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1187 assert (ObjectSynchronizer::verify_objmon_isinpool(inf), "monitor is invalid");
a61af66fc99e Initial load
duke
parents:
diff changeset
1188 return inf ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1189 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1190
a61af66fc99e Initial load
duke
parents:
diff changeset
1191 // CASE: inflation in progress - inflating over a stack-lock.
a61af66fc99e Initial load
duke
parents:
diff changeset
1192 // Some other thread is converting from stack-locked to inflated.
a61af66fc99e Initial load
duke
parents:
diff changeset
1193 // Only that thread can complete inflation -- other threads must wait.
a61af66fc99e Initial load
duke
parents:
diff changeset
1194 // The INFLATING value is transient.
a61af66fc99e Initial load
duke
parents:
diff changeset
1195 // Currently, we spin/yield/park and poll the markword, waiting for inflation to finish.
a61af66fc99e Initial load
duke
parents:
diff changeset
1196 // We could always eliminate polling by parking the thread on some auxiliary list.
a61af66fc99e Initial load
duke
parents:
diff changeset
1197 if (mark == markOopDesc::INFLATING()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1198 TEVENT (Inflate: spin while INFLATING) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1199 ReadStableMark(object) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1200 continue ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1201 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1202
a61af66fc99e Initial load
duke
parents:
diff changeset
1203 // CASE: stack-locked
a61af66fc99e Initial load
duke
parents:
diff changeset
1204 // Could be stack-locked either by this thread or by some other thread.
a61af66fc99e Initial load
duke
parents:
diff changeset
1205 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1206 // Note that we allocate the objectmonitor speculatively, _before_ attempting
a61af66fc99e Initial load
duke
parents:
diff changeset
1207 // to install INFLATING into the mark word. We originally installed INFLATING,
a61af66fc99e Initial load
duke
parents:
diff changeset
1208 // allocated the objectmonitor, and then finally STed the address of the
a61af66fc99e Initial load
duke
parents:
diff changeset
1209 // objectmonitor into the mark. This was correct, but artificially lengthened
a61af66fc99e Initial load
duke
parents:
diff changeset
1210 // the interval in which INFLATED appeared in the mark, thus increasing
a61af66fc99e Initial load
duke
parents:
diff changeset
1211 // the odds of inflation contention.
a61af66fc99e Initial load
duke
parents:
diff changeset
1212 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1213 // We now use per-thread private objectmonitor free lists.
a61af66fc99e Initial load
duke
parents:
diff changeset
1214 // These list are reprovisioned from the global free list outside the
a61af66fc99e Initial load
duke
parents:
diff changeset
1215 // critical INFLATING...ST interval. A thread can transfer
a61af66fc99e Initial load
duke
parents:
diff changeset
1216 // multiple objectmonitors en-mass from the global free list to its local free list.
a61af66fc99e Initial load
duke
parents:
diff changeset
1217 // This reduces coherency traffic and lock contention on the global free list.
a61af66fc99e Initial load
duke
parents:
diff changeset
1218 // Using such local free lists, it doesn't matter if the omAlloc() call appears
a61af66fc99e Initial load
duke
parents:
diff changeset
1219 // before or after the CAS(INFLATING) operation.
a61af66fc99e Initial load
duke
parents:
diff changeset
1220 // See the comments in omAlloc().
a61af66fc99e Initial load
duke
parents:
diff changeset
1221
a61af66fc99e Initial load
duke
parents:
diff changeset
1222 if (mark->has_locker()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1223 ObjectMonitor * m = omAlloc (Self) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1224 // Optimistically prepare the objectmonitor - anticipate successful CAS
a61af66fc99e Initial load
duke
parents:
diff changeset
1225 // We do this before the CAS in order to minimize the length of time
a61af66fc99e Initial load
duke
parents:
diff changeset
1226 // in which INFLATING appears in the mark.
a61af66fc99e Initial load
duke
parents:
diff changeset
1227 m->Recycle();
a61af66fc99e Initial load
duke
parents:
diff changeset
1228 m->_Responsible = NULL ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1229 m->OwnerIsThread = 0 ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1230 m->_recursions = 0 ;
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1231 m->_SpinDuration = ObjectMonitor::Knob_SpinLimit ; // Consider: maintain by type/class
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1232
a61af66fc99e Initial load
duke
parents:
diff changeset
1233 markOop cmp = (markOop) Atomic::cmpxchg_ptr (markOopDesc::INFLATING(), object->mark_addr(), mark) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1234 if (cmp != mark) {
1640
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1235 omRelease (Self, m, true) ;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1236 continue ; // Interference -- just retry
a61af66fc99e Initial load
duke
parents:
diff changeset
1237 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1238
a61af66fc99e Initial load
duke
parents:
diff changeset
1239 // We've successfully installed INFLATING (0) into the mark-word.
a61af66fc99e Initial load
duke
parents:
diff changeset
1240 // This is the only case where 0 will appear in a mark-work.
a61af66fc99e Initial load
duke
parents:
diff changeset
1241 // Only the singular thread that successfully swings the mark-word
a61af66fc99e Initial load
duke
parents:
diff changeset
1242 // to 0 can perform (or more precisely, complete) inflation.
a61af66fc99e Initial load
duke
parents:
diff changeset
1243 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1244 // Why do we CAS a 0 into the mark-word instead of just CASing the
a61af66fc99e Initial load
duke
parents:
diff changeset
1245 // mark-word from the stack-locked value directly to the new inflated state?
a61af66fc99e Initial load
duke
parents:
diff changeset
1246 // Consider what happens when a thread unlocks a stack-locked object.
a61af66fc99e Initial load
duke
parents:
diff changeset
1247 // It attempts to use CAS to swing the displaced header value from the
a61af66fc99e Initial load
duke
parents:
diff changeset
1248 // on-stack basiclock back into the object header. Recall also that the
a61af66fc99e Initial load
duke
parents:
diff changeset
1249 // header value (hashcode, etc) can reside in (a) the object header, or
a61af66fc99e Initial load
duke
parents:
diff changeset
1250 // (b) a displaced header associated with the stack-lock, or (c) a displaced
a61af66fc99e Initial load
duke
parents:
diff changeset
1251 // header in an objectMonitor. The inflate() routine must copy the header
a61af66fc99e Initial load
duke
parents:
diff changeset
1252 // value from the basiclock on the owner's stack to the objectMonitor, all
a61af66fc99e Initial load
duke
parents:
diff changeset
1253 // the while preserving the hashCode stability invariants. If the owner
a61af66fc99e Initial load
duke
parents:
diff changeset
1254 // decides to release the lock while the value is 0, the unlock will fail
a61af66fc99e Initial load
duke
parents:
diff changeset
1255 // and control will eventually pass from slow_exit() to inflate. The owner
a61af66fc99e Initial load
duke
parents:
diff changeset
1256 // will then spin, waiting for the 0 value to disappear. Put another way,
a61af66fc99e Initial load
duke
parents:
diff changeset
1257 // the 0 causes the owner to stall if the owner happens to try to
a61af66fc99e Initial load
duke
parents:
diff changeset
1258 // drop the lock (restoring the header from the basiclock to the object)
a61af66fc99e Initial load
duke
parents:
diff changeset
1259 // while inflation is in-progress. This protocol avoids races that might
a61af66fc99e Initial load
duke
parents:
diff changeset
1260 // would otherwise permit hashCode values to change or "flicker" for an object.
a61af66fc99e Initial load
duke
parents:
diff changeset
1261 // Critically, while object->mark is 0 mark->displaced_mark_helper() is stable.
a61af66fc99e Initial load
duke
parents:
diff changeset
1262 // 0 serves as a "BUSY" inflate-in-progress indicator.
a61af66fc99e Initial load
duke
parents:
diff changeset
1263
a61af66fc99e Initial load
duke
parents:
diff changeset
1264
a61af66fc99e Initial load
duke
parents:
diff changeset
1265 // fetch the displaced mark from the owner's stack.
a61af66fc99e Initial load
duke
parents:
diff changeset
1266 // The owner can't die or unwind past the lock while our INFLATING
a61af66fc99e Initial load
duke
parents:
diff changeset
1267 // object is in the mark. Furthermore the owner can't complete
a61af66fc99e Initial load
duke
parents:
diff changeset
1268 // an unlock on the object, either.
a61af66fc99e Initial load
duke
parents:
diff changeset
1269 markOop dmw = mark->displaced_mark_helper() ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1270 assert (dmw->is_neutral(), "invariant") ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1271
a61af66fc99e Initial load
duke
parents:
diff changeset
1272 // Setup monitor fields to proper values -- prepare the monitor
a61af66fc99e Initial load
duke
parents:
diff changeset
1273 m->set_header(dmw) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1274
a61af66fc99e Initial load
duke
parents:
diff changeset
1275 // Optimization: if the mark->locker stack address is associated
a61af66fc99e Initial load
duke
parents:
diff changeset
1276 // with this thread we could simply set m->_owner = Self and
702
b9fba36710f2 6699669: Hotspot server leaves synchronized block with monitor in bad state
xlu
parents: 579
diff changeset
1277 // m->OwnerIsThread = 1. Note that a thread can inflate an object
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1278 // that it has stack-locked -- as might happen in wait() -- directly
a61af66fc99e Initial load
duke
parents:
diff changeset
1279 // with CAS. That is, we can avoid the xchg-NULL .... ST idiom.
702
b9fba36710f2 6699669: Hotspot server leaves synchronized block with monitor in bad state
xlu
parents: 579
diff changeset
1280 m->set_owner(mark->locker());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1281 m->set_object(object);
a61af66fc99e Initial load
duke
parents:
diff changeset
1282 // TODO-FIXME: assert BasicLock->dhw != 0.
a61af66fc99e Initial load
duke
parents:
diff changeset
1283
a61af66fc99e Initial load
duke
parents:
diff changeset
1284 // Must preserve store ordering. The monitor state must
a61af66fc99e Initial load
duke
parents:
diff changeset
1285 // be stable at the time of publishing the monitor address.
a61af66fc99e Initial load
duke
parents:
diff changeset
1286 guarantee (object->mark() == markOopDesc::INFLATING(), "invariant") ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1287 object->release_set_mark(markOopDesc::encode(m));
a61af66fc99e Initial load
duke
parents:
diff changeset
1288
a61af66fc99e Initial load
duke
parents:
diff changeset
1289 // Hopefully the performance counters are allocated on distinct cache lines
a61af66fc99e Initial load
duke
parents:
diff changeset
1290 // to avoid false sharing on MP systems ...
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1291 if (ObjectMonitor::_sync_Inflations != NULL) ObjectMonitor::_sync_Inflations->inc() ;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1292 TEVENT(Inflate: overwrite stacklock) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1293 if (TraceMonitorInflation) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1294 if (object->is_instance()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1295 ResourceMark rm;
a61af66fc99e Initial load
duke
parents:
diff changeset
1296 tty->print_cr("Inflating object " INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s",
a61af66fc99e Initial load
duke
parents:
diff changeset
1297 (intptr_t) object, (intptr_t) object->mark(),
a61af66fc99e Initial load
duke
parents:
diff changeset
1298 Klass::cast(object->klass())->external_name());
a61af66fc99e Initial load
duke
parents:
diff changeset
1299 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1300 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1301 return m ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1302 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1303
a61af66fc99e Initial load
duke
parents:
diff changeset
1304 // CASE: neutral
a61af66fc99e Initial load
duke
parents:
diff changeset
1305 // TODO-FIXME: for entry we currently inflate and then try to CAS _owner.
a61af66fc99e Initial load
duke
parents:
diff changeset
1306 // If we know we're inflating for entry it's better to inflate by swinging a
a61af66fc99e Initial load
duke
parents:
diff changeset
1307 // pre-locked objectMonitor pointer into the object header. A successful
a61af66fc99e Initial load
duke
parents:
diff changeset
1308 // CAS inflates the object *and* confers ownership to the inflating thread.
a61af66fc99e Initial load
duke
parents:
diff changeset
1309 // In the current implementation we use a 2-step mechanism where we CAS()
a61af66fc99e Initial load
duke
parents:
diff changeset
1310 // to inflate and then CAS() again to try to swing _owner from NULL to Self.
a61af66fc99e Initial load
duke
parents:
diff changeset
1311 // An inflateTry() method that we could call from fast_enter() and slow_enter()
a61af66fc99e Initial load
duke
parents:
diff changeset
1312 // would be useful.
a61af66fc99e Initial load
duke
parents:
diff changeset
1313
a61af66fc99e Initial load
duke
parents:
diff changeset
1314 assert (mark->is_neutral(), "invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
1315 ObjectMonitor * m = omAlloc (Self) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1316 // prepare m for installation - set monitor to initial state
a61af66fc99e Initial load
duke
parents:
diff changeset
1317 m->Recycle();
a61af66fc99e Initial load
duke
parents:
diff changeset
1318 m->set_header(mark);
a61af66fc99e Initial load
duke
parents:
diff changeset
1319 m->set_owner(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
1320 m->set_object(object);
a61af66fc99e Initial load
duke
parents:
diff changeset
1321 m->OwnerIsThread = 1 ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1322 m->_recursions = 0 ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1323 m->_Responsible = NULL ;
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1324 m->_SpinDuration = ObjectMonitor::Knob_SpinLimit ; // consider: keep metastats by type/class
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1325
a61af66fc99e Initial load
duke
parents:
diff changeset
1326 if (Atomic::cmpxchg_ptr (markOopDesc::encode(m), object->mark_addr(), mark) != mark) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1327 m->set_object (NULL) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1328 m->set_owner (NULL) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1329 m->OwnerIsThread = 0 ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1330 m->Recycle() ;
1640
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1331 omRelease (Self, m, true) ;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1332 m = NULL ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1333 continue ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1334 // interference - the markword changed - just retry.
a61af66fc99e Initial load
duke
parents:
diff changeset
1335 // The state-transitions are one-way, so there's no chance of
a61af66fc99e Initial load
duke
parents:
diff changeset
1336 // live-lock -- "Inflated" is an absorbing state.
a61af66fc99e Initial load
duke
parents:
diff changeset
1337 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1338
a61af66fc99e Initial load
duke
parents:
diff changeset
1339 // Hopefully the performance counters are allocated on distinct
a61af66fc99e Initial load
duke
parents:
diff changeset
1340 // cache lines to avoid false sharing on MP systems ...
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1341 if (ObjectMonitor::_sync_Inflations != NULL) ObjectMonitor::_sync_Inflations->inc() ;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1342 TEVENT(Inflate: overwrite neutral) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1343 if (TraceMonitorInflation) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1344 if (object->is_instance()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1345 ResourceMark rm;
a61af66fc99e Initial load
duke
parents:
diff changeset
1346 tty->print_cr("Inflating object " INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s",
a61af66fc99e Initial load
duke
parents:
diff changeset
1347 (intptr_t) object, (intptr_t) object->mark(),
a61af66fc99e Initial load
duke
parents:
diff changeset
1348 Klass::cast(object->klass())->external_name());
a61af66fc99e Initial load
duke
parents:
diff changeset
1349 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1350 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1351 return m ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1352 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1353 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1354
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1355 // Note that we could encounter some performance loss through false-sharing as
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1356 // multiple locks occupy the same $ line. Padding might be appropriate.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1357
a61af66fc99e Initial load
duke
parents:
diff changeset
1358
a61af66fc99e Initial load
duke
parents:
diff changeset
1359 // Deflate_idle_monitors() is called at all safepoints, immediately
a61af66fc99e Initial load
duke
parents:
diff changeset
1360 // after all mutators are stopped, but before any objects have moved.
a61af66fc99e Initial load
duke
parents:
diff changeset
1361 // It traverses the list of known monitors, deflating where possible.
a61af66fc99e Initial load
duke
parents:
diff changeset
1362 // The scavenged monitor are returned to the monitor free list.
a61af66fc99e Initial load
duke
parents:
diff changeset
1363 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1364 // Beware that we scavenge at *every* stop-the-world point.
a61af66fc99e Initial load
duke
parents:
diff changeset
1365 // Having a large number of monitors in-circulation negatively
a61af66fc99e Initial load
duke
parents:
diff changeset
1366 // impacts the performance of some applications (e.g., PointBase).
a61af66fc99e Initial load
duke
parents:
diff changeset
1367 // Broadly, we want to minimize the # of monitors in circulation.
1587
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1368 //
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1369 // We have added a flag, MonitorInUseLists, which creates a list
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1370 // of active monitors for each thread. deflate_idle_monitors()
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1371 // only scans the per-thread inuse lists. omAlloc() puts all
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1372 // assigned monitors on the per-thread list. deflate_idle_monitors()
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1373 // returns the non-busy monitors to the global free list.
1640
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1374 // When a thread dies, omFlush() adds the list of active monitors for
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1375 // that thread to a global gOmInUseList acquiring the
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1376 // global list lock. deflate_idle_monitors() acquires the global
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1377 // list lock to scan for non-busy monitors to the global free list.
1587
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1378 // An alternative could have used a single global inuse list. The
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1379 // downside would have been the additional cost of acquiring the global list lock
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1380 // for every omAlloc().
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1381 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1382 // Perversely, the heap size -- and thus the STW safepoint rate --
a61af66fc99e Initial load
duke
parents:
diff changeset
1383 // typically drives the scavenge rate. Large heaps can mean infrequent GC,
a61af66fc99e Initial load
duke
parents:
diff changeset
1384 // which in turn can mean large(r) numbers of objectmonitors in circulation.
a61af66fc99e Initial load
duke
parents:
diff changeset
1385 // This is an unfortunate aspect of this design.
a61af66fc99e Initial load
duke
parents:
diff changeset
1386 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1387
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1388 enum ManifestConstants {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1389 ClearResponsibleAtSTW = 0,
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1390 MaximumRecheckInterval = 1000
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1391 } ;
1587
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1392
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1393 // Deflate a single monitor if not in use
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1394 // Return true if deflated, false if in use
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1395 bool ObjectSynchronizer::deflate_monitor(ObjectMonitor* mid, oop obj,
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1396 ObjectMonitor** FreeHeadp, ObjectMonitor** FreeTailp) {
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1397 bool deflated;
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1398 // Normal case ... The monitor is associated with obj.
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1399 guarantee (obj->mark() == markOopDesc::encode(mid), "invariant") ;
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1400 guarantee (mid == obj->mark()->monitor(), "invariant");
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1401 guarantee (mid->header()->is_neutral(), "invariant");
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1402
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1403 if (mid->is_busy()) {
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1404 if (ClearResponsibleAtSTW) mid->_Responsible = NULL ;
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1405 deflated = false;
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1406 } else {
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1407 // Deflate the monitor if it is no longer being used
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1408 // It's idle - scavenge and return to the global free list
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1409 // plain old deflation ...
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1410 TEVENT (deflate_idle_monitors - scavenge1) ;
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1411 if (TraceMonitorInflation) {
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1412 if (obj->is_instance()) {
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1413 ResourceMark rm;
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1414 tty->print_cr("Deflating object " INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s",
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1415 (intptr_t) obj, (intptr_t) obj->mark(), Klass::cast(obj->klass())->external_name());
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1416 }
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1417 }
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1418
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1419 // Restore the header back to obj
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1420 obj->release_set_mark(mid->header());
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1421 mid->clear();
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1422
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1423 assert (mid->object() == NULL, "invariant") ;
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1424
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1425 // Move the object to the working free list defined by FreeHead,FreeTail.
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1426 if (*FreeHeadp == NULL) *FreeHeadp = mid;
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1427 if (*FreeTailp != NULL) {
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1428 ObjectMonitor * prevtail = *FreeTailp;
1640
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1429 assert(prevtail->FreeNext == NULL, "cleaned up deflated?"); // TODO KK
1587
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1430 prevtail->FreeNext = mid;
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1431 }
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1432 *FreeTailp = mid;
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1433 deflated = true;
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1434 }
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1435 return deflated;
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1436 }
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1437
1640
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1438 // Caller acquires ListLock
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1439 int ObjectSynchronizer::walk_monitor_list(ObjectMonitor** listheadp,
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1440 ObjectMonitor** FreeHeadp, ObjectMonitor** FreeTailp) {
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1441 ObjectMonitor* mid;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1442 ObjectMonitor* next;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1443 ObjectMonitor* curmidinuse = NULL;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1444 int deflatedcount = 0;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1445
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1446 for (mid = *listheadp; mid != NULL; ) {
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1447 oop obj = (oop) mid->object();
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1448 bool deflated = false;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1449 if (obj != NULL) {
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1450 deflated = deflate_monitor(mid, obj, FreeHeadp, FreeTailp);
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1451 }
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1452 if (deflated) {
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1453 // extract from per-thread in-use-list
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1454 if (mid == *listheadp) {
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1455 *listheadp = mid->FreeNext;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1456 } else if (curmidinuse != NULL) {
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1457 curmidinuse->FreeNext = mid->FreeNext; // maintain the current thread inuselist
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1458 }
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1459 next = mid->FreeNext;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1460 mid->FreeNext = NULL; // This mid is current tail in the FreeHead list
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1461 mid = next;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1462 deflatedcount++;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1463 } else {
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1464 curmidinuse = mid;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1465 mid = mid->FreeNext;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1466 }
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1467 }
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1468 return deflatedcount;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1469 }
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1470
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1471 void ObjectSynchronizer::deflate_idle_monitors() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1472 assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
a61af66fc99e Initial load
duke
parents:
diff changeset
1473 int nInuse = 0 ; // currently associated with objects
a61af66fc99e Initial load
duke
parents:
diff changeset
1474 int nInCirculation = 0 ; // extant
a61af66fc99e Initial load
duke
parents:
diff changeset
1475 int nScavenged = 0 ; // reclaimed
1587
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1476 bool deflated = false;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1477
a61af66fc99e Initial load
duke
parents:
diff changeset
1478 ObjectMonitor * FreeHead = NULL ; // Local SLL of scavenged monitors
a61af66fc99e Initial load
duke
parents:
diff changeset
1479 ObjectMonitor * FreeTail = NULL ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1480
1587
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1481 TEVENT (deflate_idle_monitors) ;
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1482 // Prevent omFlush from changing mids in Thread dtor's during deflation
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1483 // And in case the vm thread is acquiring a lock during a safepoint
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1484 // See e.g. 6320749
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1485 Thread::muxAcquire (&ListLock, "scavenge - return") ;
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1486
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1487 if (MonitorInUseLists) {
1640
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1488 int inUse = 0;
1587
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1489 for (JavaThread* cur = Threads::first(); cur != NULL; cur = cur->next()) {
1640
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1490 nInCirculation+= cur->omInUseCount;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1491 int deflatedcount = walk_monitor_list(cur->omInUseList_addr(), &FreeHead, &FreeTail);
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1492 cur->omInUseCount-= deflatedcount;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1493 // verifyInUse(cur);
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1494 nScavenged += deflatedcount;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1495 nInuse += cur->omInUseCount;
1587
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1496 }
1640
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1497
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1498 // For moribund threads, scan gOmInUseList
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1499 if (gOmInUseList) {
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1500 nInCirculation += gOmInUseCount;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1501 int deflatedcount = walk_monitor_list((ObjectMonitor **)&gOmInUseList, &FreeHead, &FreeTail);
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1502 gOmInUseCount-= deflatedcount;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1503 nScavenged += deflatedcount;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1504 nInuse += gOmInUseCount;
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1505 }
bfc89697cccb 6964164: MonitorInUseLists leak of contended objects
acorn
parents: 1589
diff changeset
1506
1587
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1507 } else for (ObjectMonitor* block = gBlockList; block != NULL; block = next(block)) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1508 // Iterate over all extant monitors - Scavenge all idle monitors.
a61af66fc99e Initial load
duke
parents:
diff changeset
1509 assert(block->object() == CHAINMARKER, "must be a block header");
a61af66fc99e Initial load
duke
parents:
diff changeset
1510 nInCirculation += _BLOCKSIZE ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1511 for (int i = 1 ; i < _BLOCKSIZE; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1512 ObjectMonitor* mid = &block[i];
a61af66fc99e Initial load
duke
parents:
diff changeset
1513 oop obj = (oop) mid->object();
a61af66fc99e Initial load
duke
parents:
diff changeset
1514
a61af66fc99e Initial load
duke
parents:
diff changeset
1515 if (obj == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1516 // The monitor is not associated with an object.
a61af66fc99e Initial load
duke
parents:
diff changeset
1517 // The monitor should either be a thread-specific private
a61af66fc99e Initial load
duke
parents:
diff changeset
1518 // free list or the global free list.
a61af66fc99e Initial load
duke
parents:
diff changeset
1519 // obj == NULL IMPLIES mid->is_busy() == 0
a61af66fc99e Initial load
duke
parents:
diff changeset
1520 guarantee (!mid->is_busy(), "invariant") ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1521 continue ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1522 }
1587
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1523 deflated = deflate_monitor(mid, obj, &FreeHead, &FreeTail);
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1524
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1525 if (deflated) {
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1526 mid->FreeNext = NULL ;
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1527 nScavenged ++ ;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1528 } else {
1587
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1529 nInuse ++;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1530 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1531 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1532 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1533
1587
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1534 MonitorFreeCount += nScavenged;
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1535
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1536 // Consider: audit gFreeList to ensure that MonitorFreeCount and list agree.
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1537
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1538 if (ObjectMonitor::Knob_Verbose) {
1587
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1539 ::printf ("Deflate: InCirc=%d InUse=%d Scavenged=%d ForceMonitorScavenge=%d : pop=%d free=%d\n",
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1540 nInCirculation, nInuse, nScavenged, ForceMonitorScavenge,
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1541 MonitorPopulation, MonitorFreeCount) ;
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1542 ::fflush(stdout) ;
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1543 }
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1544
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1545 ForceMonitorScavenge = 0; // Reset
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1546
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1547 // Move the scavenged monitors back to the global free list.
a61af66fc99e Initial load
duke
parents:
diff changeset
1548 if (FreeHead != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1549 guarantee (FreeTail != NULL && nScavenged > 0, "invariant") ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1550 assert (FreeTail->FreeNext == NULL, "invariant") ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1551 // constant-time list splice - prepend scavenged segment to gFreeList
a61af66fc99e Initial load
duke
parents:
diff changeset
1552 FreeTail->FreeNext = gFreeList ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1553 gFreeList = FreeHead ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1554 }
1587
b96a3e44582f 6852873: Reduce safepoint cleanup time
acorn
parents: 702
diff changeset
1555 Thread::muxRelease (&ListLock) ;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1556
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1557 if (ObjectMonitor::_sync_Deflations != NULL) ObjectMonitor::_sync_Deflations->inc(nScavenged) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1558 if (ObjectMonitor::_sync_MonExtant != NULL) ObjectMonitor::_sync_MonExtant ->set_value(nInCirculation);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1559
a61af66fc99e Initial load
duke
parents:
diff changeset
1560 // TODO: Add objectMonitor leak detection.
a61af66fc99e Initial load
duke
parents:
diff changeset
1561 // Audit/inventory the objectMonitors -- make sure they're all accounted for.
a61af66fc99e Initial load
duke
parents:
diff changeset
1562 GVars.stwRandom = os::random() ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1563 GVars.stwCycle ++ ;
a61af66fc99e Initial load
duke
parents:
diff changeset
1564 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1565
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1566 // Monitor cleanup on JavaThread::exit
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1567
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1568 // Iterate through monitor cache and attempt to release thread's monitors
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1569 // Gives up on a particular monitor if an exception occurs, but continues
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1570 // the overall iteration, swallowing the exception.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1571 class ReleaseJavaMonitorsClosure: public MonitorClosure {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1572 private:
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1573 TRAPS;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1574
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1575 public:
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1576 ReleaseJavaMonitorsClosure(Thread* thread) : THREAD(thread) {}
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1577 void do_monitor(ObjectMonitor* mid) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1578 if (mid->owner() == THREAD) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1579 (void)mid->complete_exit(CHECK);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1580 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1581 }
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1582 };
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1583
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1584 // Release all inflated monitors owned by THREAD. Lightweight monitors are
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1585 // ignored. This is meant to be called during JNI thread detach which assumes
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1586 // all remaining monitors are heavyweight. All exceptions are swallowed.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1587 // Scanning the extant monitor list can be time consuming.
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1588 // A simple optimization is to add a per-thread flag that indicates a thread
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1589 // called jni_monitorenter() during its lifetime.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1590 //
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1591 // Instead of No_Savepoint_Verifier it might be cheaper to
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1592 // use an idiom of the form:
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1593 // auto int tmp = SafepointSynchronize::_safepoint_counter ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1594 // <code that must not run at safepoint>
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1595 // guarantee (((tmp ^ _safepoint_counter) | (tmp & 1)) == 0) ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1596 // Since the tests are extremely cheap we could leave them enabled
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1597 // for normal product builds.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1598
1878
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1599 void ObjectSynchronizer::release_monitors_owned_by_thread(TRAPS) {
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1600 assert(THREAD == JavaThread::current(), "must be current Java thread");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1601 No_Safepoint_Verifier nsv ;
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1602 ReleaseJavaMonitorsClosure rjmc(THREAD);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1603 Thread::muxAcquire(&ListLock, "release_monitors_owned_by_thread");
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1604 ObjectSynchronizer::monitors_iterate(&rjmc);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1605 Thread::muxRelease(&ListLock);
fa83ab460c54 6988353: refactor contended sync subsystem
acorn
parents: 1640
diff changeset
1606 THREAD->clear_pending_exception();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1607 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1608
a61af66fc99e Initial load
duke
parents:
diff changeset
1609 //------------------------------------------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
1610 // Non-product code
a61af66fc99e Initial load
duke
parents:
diff changeset
1611
a61af66fc99e Initial load
duke
parents:
diff changeset
1612 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
1613
a61af66fc99e Initial load
duke
parents:
diff changeset
1614 void ObjectSynchronizer::trace_locking(Handle locking_obj, bool is_compiled,
a61af66fc99e Initial load
duke
parents:
diff changeset
1615 bool is_method, bool is_locking) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1616 // Don't know what to do here
a61af66fc99e Initial load
duke
parents:
diff changeset
1617 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1618
a61af66fc99e Initial load
duke
parents:
diff changeset
1619 // Verify all monitors in the monitor cache, the verification is weak.
a61af66fc99e Initial load
duke
parents:
diff changeset
1620 void ObjectSynchronizer::verify() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1621 ObjectMonitor* block = gBlockList;
a61af66fc99e Initial load
duke
parents:
diff changeset
1622 ObjectMonitor* mid;
a61af66fc99e Initial load
duke
parents:
diff changeset
1623 while (block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1624 assert(block->object() == CHAINMARKER, "must be a block header");
a61af66fc99e Initial load
duke
parents:
diff changeset
1625 for (int i = 1; i < _BLOCKSIZE; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1626 mid = block + i;
a61af66fc99e Initial load
duke
parents:
diff changeset
1627 oop object = (oop) mid->object();
a61af66fc99e Initial load
duke
parents:
diff changeset
1628 if (object != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1629 mid->verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
1630 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1631 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1632 block = (ObjectMonitor*) block->FreeNext;
a61af66fc99e Initial load
duke
parents:
diff changeset
1633 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1634 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1635
a61af66fc99e Initial load
duke
parents:
diff changeset
1636 // Check if monitor belongs to the monitor cache
a61af66fc99e Initial load
duke
parents:
diff changeset
1637 // The list is grow-only so it's *relatively* safe to traverse
a61af66fc99e Initial load
duke
parents:
diff changeset
1638 // the list of extant blocks without taking a lock.
a61af66fc99e Initial load
duke
parents:
diff changeset
1639
a61af66fc99e Initial load
duke
parents:
diff changeset
1640 int ObjectSynchronizer::verify_objmon_isinpool(ObjectMonitor *monitor) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1641 ObjectMonitor* block = gBlockList;
a61af66fc99e Initial load
duke
parents:
diff changeset
1642
a61af66fc99e Initial load
duke
parents:
diff changeset
1643 while (block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1644 assert(block->object() == CHAINMARKER, "must be a block header");
a61af66fc99e Initial load
duke
parents:
diff changeset
1645 if (monitor > &block[0] && monitor < &block[_BLOCKSIZE]) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1646 address mon = (address) monitor;
a61af66fc99e Initial load
duke
parents:
diff changeset
1647 address blk = (address) block;
a61af66fc99e Initial load
duke
parents:
diff changeset
1648 size_t diff = mon - blk;
a61af66fc99e Initial load
duke
parents:
diff changeset
1649 assert((diff % sizeof(ObjectMonitor)) == 0, "check");
a61af66fc99e Initial load
duke
parents:
diff changeset
1650 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
1651 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1652 block = (ObjectMonitor*) block->FreeNext;
a61af66fc99e Initial load
duke
parents:
diff changeset
1653 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1654 return 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1655 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1656
a61af66fc99e Initial load
duke
parents:
diff changeset
1657 #endif