Mercurial > hg > truffle
annotate agent/src/share/classes/sun/jvm/hotspot/oops/Mark.java @ 3972:4f93f0d00802
7059019: G1: add G1 support to the SA
Summary: Extend the SA to recognize the G1CollectedHeap and implement any code that's needed by our serviceability tools (jmap, jinfo, jstack, etc.) that depend on the SA.
Reviewed-by: never, poonam, johnc
author | tonyp |
---|---|
date | Tue, 20 Sep 2011 09:59:59 -0400 |
parents | c18cbe5936b8 |
children |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
196
diff
changeset
|
2 * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
196
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
196
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:
196
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 package sun.jvm.hotspot.oops; | |
26 | |
27 import java.io.*; | |
28 import java.util.*; | |
29 | |
30 import sun.jvm.hotspot.debugger.*; | |
31 import sun.jvm.hotspot.runtime.*; | |
32 import sun.jvm.hotspot.types.*; | |
33 import sun.jvm.hotspot.utilities.*; | |
34 | |
35 /** Mark is the analogue of the VM's markOop. In this system it does | |
36 not subclass Oop but VMObject. For a mark on the stack, the mark's | |
37 address will be an Address; for a mark in the header of an object, | |
38 it will be an OopHandle. It is assumed in a couple of places in | |
39 this code that the mark is the first word in an object. */ | |
40 | |
41 public class Mark extends VMObject { | |
42 static { | |
43 VM.registerVMInitializedObserver(new Observer() { | |
44 public void update(Observable o, Object data) { | |
45 initialize(VM.getVM().getTypeDataBase()); | |
46 } | |
47 }); | |
48 } | |
49 | |
50 private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { | |
51 Type type = db.lookupType("oopDesc"); | |
52 markField = type.getCIntegerField("_mark"); | |
53 | |
54 ageBits = db.lookupLongConstant("markOopDesc::age_bits").longValue(); | |
55 lockBits = db.lookupLongConstant("markOopDesc::lock_bits").longValue(); | |
56 biasedLockBits = db.lookupLongConstant("markOopDesc::biased_lock_bits").longValue(); | |
57 maxHashBits = db.lookupLongConstant("markOopDesc::max_hash_bits").longValue(); | |
58 hashBits = db.lookupLongConstant("markOopDesc::hash_bits").longValue(); | |
59 lockShift = db.lookupLongConstant("markOopDesc::lock_shift").longValue(); | |
60 biasedLockShift = db.lookupLongConstant("markOopDesc::biased_lock_shift").longValue(); | |
61 ageShift = db.lookupLongConstant("markOopDesc::age_shift").longValue(); | |
62 hashShift = db.lookupLongConstant("markOopDesc::hash_shift").longValue(); | |
63 lockMask = db.lookupLongConstant("markOopDesc::lock_mask").longValue(); | |
64 lockMaskInPlace = db.lookupLongConstant("markOopDesc::lock_mask_in_place").longValue(); | |
65 biasedLockMask = db.lookupLongConstant("markOopDesc::biased_lock_mask").longValue(); | |
66 biasedLockMaskInPlace = db.lookupLongConstant("markOopDesc::biased_lock_mask_in_place").longValue(); | |
67 biasedLockBitInPlace = db.lookupLongConstant("markOopDesc::biased_lock_bit_in_place").longValue(); | |
68 ageMask = db.lookupLongConstant("markOopDesc::age_mask").longValue(); | |
69 ageMaskInPlace = db.lookupLongConstant("markOopDesc::age_mask_in_place").longValue(); | |
70 hashMask = db.lookupLongConstant("markOopDesc::hash_mask").longValue(); | |
71 hashMaskInPlace = db.lookupLongConstant("markOopDesc::hash_mask_in_place").longValue(); | |
72 biasedLockAlignment = db.lookupLongConstant("markOopDesc::biased_lock_alignment").longValue(); | |
73 lockedValue = db.lookupLongConstant("markOopDesc::locked_value").longValue(); | |
74 unlockedValue = db.lookupLongConstant("markOopDesc::unlocked_value").longValue(); | |
75 monitorValue = db.lookupLongConstant("markOopDesc::monitor_value").longValue(); | |
76 markedValue = db.lookupLongConstant("markOopDesc::marked_value").longValue(); | |
77 biasedLockPattern = db.lookupLongConstant("markOopDesc::biased_lock_pattern").longValue(); | |
78 noHash = db.lookupLongConstant("markOopDesc::no_hash").longValue(); | |
79 noHashInPlace = db.lookupLongConstant("markOopDesc::no_hash_in_place").longValue(); | |
80 noLockInPlace = db.lookupLongConstant("markOopDesc::no_lock_in_place").longValue(); | |
81 maxAge = db.lookupLongConstant("markOopDesc::max_age").longValue(); | |
187 | 82 |
83 /* Constants in markOop used by CMS. */ | |
84 cmsShift = db.lookupLongConstant("markOopDesc::cms_shift").longValue(); | |
85 cmsMask = db.lookupLongConstant("markOopDesc::cms_mask").longValue(); | |
86 sizeShift = db.lookupLongConstant("markOopDesc::size_shift").longValue(); | |
0 | 87 } |
88 | |
89 // Field accessors | |
90 private static CIntegerField markField; | |
91 | |
92 // Constants -- read from VM | |
93 private static long ageBits; | |
94 private static long lockBits; | |
95 private static long biasedLockBits; | |
96 private static long maxHashBits; | |
97 private static long hashBits; | |
98 | |
99 private static long lockShift; | |
100 private static long biasedLockShift; | |
101 private static long ageShift; | |
102 private static long hashShift; | |
103 | |
104 private static long lockMask; | |
105 private static long lockMaskInPlace; | |
106 private static long biasedLockMask; | |
107 private static long biasedLockMaskInPlace; | |
108 private static long biasedLockBitInPlace; | |
109 private static long ageMask; | |
110 private static long ageMaskInPlace; | |
111 private static long hashMask; | |
112 private static long hashMaskInPlace; | |
113 private static long biasedLockAlignment; | |
114 | |
115 private static long lockedValue; | |
116 private static long unlockedValue; | |
117 private static long monitorValue; | |
118 private static long markedValue; | |
119 private static long biasedLockPattern; | |
120 | |
121 private static long noHash; | |
122 | |
123 private static long noHashInPlace; | |
124 private static long noLockInPlace; | |
125 | |
126 private static long maxAge; | |
127 | |
187 | 128 /* Constants in markOop used by CMS. */ |
129 private static long cmsShift; | |
130 private static long cmsMask; | |
131 private static long sizeShift; | |
132 | |
0 | 133 public Mark(Address addr) { |
134 super(addr); | |
135 } | |
136 | |
137 public long value() { | |
138 return markField.getValue(addr); | |
139 } | |
140 | |
141 public Address valueAsAddress() { | |
142 return addr.getAddressAt(markField.getOffset()); | |
143 } | |
144 | |
145 // Biased locking accessors | |
146 // These must be checked by all code which calls into the | |
147 // ObjectSynchoronizer and other code. The biasing is not understood | |
148 // by the lower-level CAS-based locking code, although the runtime | |
149 // fixes up biased locks to be compatible with it when a bias is | |
150 // revoked. | |
151 public boolean hasBiasPattern() { | |
152 return (Bits.maskBitsLong(value(), biasedLockMaskInPlace) == biasedLockPattern); | |
153 } | |
154 | |
155 public JavaThread biasedLocker() { | |
156 Threads threads = VM.getVM().getThreads(); | |
157 Address addr = valueAsAddress().andWithMask(~(biasedLockMaskInPlace & ageMaskInPlace)); | |
158 return threads.createJavaThreadWrapper(addr); | |
159 } | |
160 | |
161 // Indicates that the mark gas the bias bit set but that it has not | |
162 // yet been biased toward a particular thread | |
163 public boolean isBiasedAnonymously() { | |
164 return hasBiasPattern() && (biasedLocker() == null); | |
165 } | |
166 | |
167 // lock accessors (note that these assume lock_shift == 0) | |
168 public boolean isLocked() { | |
169 return (Bits.maskBitsLong(value(), lockMaskInPlace) != unlockedValue); | |
170 } | |
171 public boolean isUnlocked() { | |
172 return (Bits.maskBitsLong(value(), biasedLockMaskInPlace) == unlockedValue); | |
173 } | |
174 public boolean isMarked() { | |
175 return (Bits.maskBitsLong(value(), lockMaskInPlace) == markedValue); | |
176 } | |
177 | |
178 // Special temporary state of the markOop while being inflated. | |
179 // Code that looks at mark outside a lock need to take this into account. | |
180 public boolean isBeingInflated() { | |
181 return (value() == 0); | |
182 } | |
183 | |
184 // Should this header be preserved during GC? | |
185 public boolean mustBePreserved() { | |
186 return (!isUnlocked() || !hasNoHash()); | |
187 } | |
188 | |
189 // WARNING: The following routines are used EXCLUSIVELY by | |
190 // synchronization functions. They are not really gc safe. | |
191 // They must get updated if markOop layout get changed. | |
192 | |
193 // FIXME | |
194 // markOop set_unlocked() const { | |
195 // return markOop(value() | unlocked_value); | |
196 // } | |
197 public boolean hasLocker() { | |
198 return ((value() & lockMaskInPlace) == lockedValue); | |
199 } | |
200 public BasicLock locker() { | |
201 if (Assert.ASSERTS_ENABLED) { | |
202 Assert.that(hasLocker(), "check"); | |
203 } | |
204 return new BasicLock(valueAsAddress()); | |
205 } | |
206 public boolean hasMonitor() { | |
207 return ((value() & monitorValue) != 0); | |
208 } | |
209 public ObjectMonitor monitor() { | |
210 if (Assert.ASSERTS_ENABLED) { | |
211 Assert.that(hasMonitor(), "check"); | |
212 } | |
213 // Use xor instead of &~ to provide one extra tag-bit check. | |
214 Address monAddr = valueAsAddress().xorWithMask(monitorValue); | |
215 return new ObjectMonitor(monAddr); | |
216 } | |
217 public boolean hasDisplacedMarkHelper() { | |
218 return ((value() & unlockedValue) == 0); | |
219 } | |
220 public Mark displacedMarkHelper() { | |
221 if (Assert.ASSERTS_ENABLED) { | |
222 Assert.that(hasDisplacedMarkHelper(), "check"); | |
223 } | |
224 Address addr = valueAsAddress().andWithMask(~monitorValue); | |
225 return new Mark(addr.getAddressAt(0)); | |
226 } | |
227 // FIXME | |
228 // void set_displaced_mark_helper(markOop m) const { | |
229 // assert(has_displaced_mark_helper(), "check"); | |
230 // intptr_t ptr = (value() & ~monitor_value); | |
231 // *(markOop*)ptr = m; | |
232 // } | |
233 // markOop copy_set_hash(intptr_t hash) const { | |
234 // intptr_t tmp = value() & (~hash_mask_in_place); | |
235 // tmp |= ((hash & hash_mask) << hash_shift); | |
236 // return (markOop)tmp; | |
237 // } | |
238 // it is only used to be stored into BasicLock as the | |
239 // indicator that the lock is using heavyweight monitor | |
240 // static markOop unused_mark() { | |
241 // return (markOop) marked_value; | |
242 // } | |
243 // // the following two functions create the markOop to be | |
244 // // stored into object header, it encodes monitor info | |
245 // static markOop encode(BasicLock* lock) { | |
246 // return (markOop) lock; | |
247 // } | |
248 // static markOop encode(ObjectMonitor* monitor) { | |
249 // intptr_t tmp = (intptr_t) monitor; | |
250 // return (markOop) (tmp | monitor_value); | |
251 // } | |
252 // used for alignment-based marking to reuse the busy state to encode pointers | |
253 // (see markOop_alignment.hpp) | |
254 // markOop clear_lock_bits() { return markOop(value() & ~lock_mask_in_place); } | |
255 // | |
256 // // age operations | |
257 // markOop set_marked() { return markOop((value() & ~lock_mask_in_place) | marked_value); } | |
258 // | |
259 public int age() { return (int) Bits.maskBitsLong(value() >> ageShift, ageMask); } | |
260 // markOop set_age(int v) const { | |
261 // assert((v & ~age_mask) == 0, "shouldn't overflow age field"); | |
262 // return markOop((value() & ~age_mask_in_place) | (((intptr_t)v & age_mask) << age_shift)); | |
263 // } | |
264 // markOop incr_age() const { return age() == max_age ? markOop(this) : set_age(age() + 1); } | |
265 | |
266 // hash operations | |
267 public long hash() { | |
268 return Bits.maskBitsLong(value() >> hashShift, hashMask); | |
269 } | |
270 | |
271 public boolean hasNoHash() { | |
272 return hash() == noHash; | |
273 } | |
274 | |
275 // FIXME | |
276 // Prototype mark for initialization | |
277 // static markOop prototype() { | |
278 // return markOop( no_hash_in_place | no_lock_in_place ); | |
279 // } | |
280 | |
281 // Debugging | |
282 public void printOn(PrintStream tty) { | |
283 if (isLocked()) { | |
284 tty.print("locked(0x" + | |
285 Long.toHexString(value()) + ")->"); | |
286 displacedMarkHelper().printOn(tty); | |
287 } else { | |
288 if (Assert.ASSERTS_ENABLED) { | |
289 Assert.that(isUnlocked(), "just checking"); | |
290 } | |
291 tty.print("mark("); | |
292 tty.print("hash " + Long.toHexString(hash()) + ","); | |
293 tty.print("age " + age() + ")"); | |
294 } | |
295 } | |
296 | |
297 // FIXME | |
298 // // Prepare address of oop for placement into mark | |
299 // inline static markOop encode_pointer_as_mark(void* p) { return markOop(p)->set_marked(); } | |
300 // | |
301 // // Recover address of oop from encoded form used in mark | |
302 // inline void* decode_pointer() { return clear_lock_bits(); } | |
187 | 303 |
304 // Copy markOop methods for CMS here. | |
305 public boolean isCmsFreeChunk() { | |
306 return isUnlocked() && | |
307 (Bits.maskBitsLong(value() >> cmsShift, cmsMask) & 0x1L) == 0x1L; | |
308 } | |
309 public long getSize() { return (long)(value() >> sizeShift); } | |
0 | 310 } |