comparison agent/src/share/classes/sun/jvm/hotspot/oops/Mark.java @ 0:a61af66fc99e jdk7-b24

Initial load
author duke
date Sat, 01 Dec 2007 00:00:00 +0000
parents
children 790e66e5fbac
comparison
equal deleted inserted replaced
-1:000000000000 0:a61af66fc99e
1 /*
2 * Copyright 2001-2005 Sun Microsystems, Inc. All Rights Reserved.
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 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
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();
82 }
83
84 // Field accessors
85 private static CIntegerField markField;
86
87 // Constants -- read from VM
88 private static long ageBits;
89 private static long lockBits;
90 private static long biasedLockBits;
91 private static long maxHashBits;
92 private static long hashBits;
93
94 private static long lockShift;
95 private static long biasedLockShift;
96 private static long ageShift;
97 private static long hashShift;
98
99 private static long lockMask;
100 private static long lockMaskInPlace;
101 private static long biasedLockMask;
102 private static long biasedLockMaskInPlace;
103 private static long biasedLockBitInPlace;
104 private static long ageMask;
105 private static long ageMaskInPlace;
106 private static long hashMask;
107 private static long hashMaskInPlace;
108 private static long biasedLockAlignment;
109
110 private static long lockedValue;
111 private static long unlockedValue;
112 private static long monitorValue;
113 private static long markedValue;
114 private static long biasedLockPattern;
115
116 private static long noHash;
117
118 private static long noHashInPlace;
119 private static long noLockInPlace;
120
121 private static long maxAge;
122
123 public Mark(Address addr) {
124 super(addr);
125 }
126
127 public long value() {
128 return markField.getValue(addr);
129 }
130
131 public Address valueAsAddress() {
132 return addr.getAddressAt(markField.getOffset());
133 }
134
135 // Biased locking accessors
136 // These must be checked by all code which calls into the
137 // ObjectSynchoronizer and other code. The biasing is not understood
138 // by the lower-level CAS-based locking code, although the runtime
139 // fixes up biased locks to be compatible with it when a bias is
140 // revoked.
141 public boolean hasBiasPattern() {
142 return (Bits.maskBitsLong(value(), biasedLockMaskInPlace) == biasedLockPattern);
143 }
144
145 public JavaThread biasedLocker() {
146 Threads threads = VM.getVM().getThreads();
147 Address addr = valueAsAddress().andWithMask(~(biasedLockMaskInPlace & ageMaskInPlace));
148 return threads.createJavaThreadWrapper(addr);
149 }
150
151 // Indicates that the mark gas the bias bit set but that it has not
152 // yet been biased toward a particular thread
153 public boolean isBiasedAnonymously() {
154 return hasBiasPattern() && (biasedLocker() == null);
155 }
156
157 // lock accessors (note that these assume lock_shift == 0)
158 public boolean isLocked() {
159 return (Bits.maskBitsLong(value(), lockMaskInPlace) != unlockedValue);
160 }
161 public boolean isUnlocked() {
162 return (Bits.maskBitsLong(value(), biasedLockMaskInPlace) == unlockedValue);
163 }
164 public boolean isMarked() {
165 return (Bits.maskBitsLong(value(), lockMaskInPlace) == markedValue);
166 }
167
168 // Special temporary state of the markOop while being inflated.
169 // Code that looks at mark outside a lock need to take this into account.
170 public boolean isBeingInflated() {
171 return (value() == 0);
172 }
173
174 // Should this header be preserved during GC?
175 public boolean mustBePreserved() {
176 return (!isUnlocked() || !hasNoHash());
177 }
178
179 // WARNING: The following routines are used EXCLUSIVELY by
180 // synchronization functions. They are not really gc safe.
181 // They must get updated if markOop layout get changed.
182
183 // FIXME
184 // markOop set_unlocked() const {
185 // return markOop(value() | unlocked_value);
186 // }
187 public boolean hasLocker() {
188 return ((value() & lockMaskInPlace) == lockedValue);
189 }
190 public BasicLock locker() {
191 if (Assert.ASSERTS_ENABLED) {
192 Assert.that(hasLocker(), "check");
193 }
194 return new BasicLock(valueAsAddress());
195 }
196 public boolean hasMonitor() {
197 return ((value() & monitorValue) != 0);
198 }
199 public ObjectMonitor monitor() {
200 if (Assert.ASSERTS_ENABLED) {
201 Assert.that(hasMonitor(), "check");
202 }
203 // Use xor instead of &~ to provide one extra tag-bit check.
204 Address monAddr = valueAsAddress().xorWithMask(monitorValue);
205 return new ObjectMonitor(monAddr);
206 }
207 public boolean hasDisplacedMarkHelper() {
208 return ((value() & unlockedValue) == 0);
209 }
210 public Mark displacedMarkHelper() {
211 if (Assert.ASSERTS_ENABLED) {
212 Assert.that(hasDisplacedMarkHelper(), "check");
213 }
214 Address addr = valueAsAddress().andWithMask(~monitorValue);
215 return new Mark(addr.getAddressAt(0));
216 }
217 // FIXME
218 // void set_displaced_mark_helper(markOop m) const {
219 // assert(has_displaced_mark_helper(), "check");
220 // intptr_t ptr = (value() & ~monitor_value);
221 // *(markOop*)ptr = m;
222 // }
223 // markOop copy_set_hash(intptr_t hash) const {
224 // intptr_t tmp = value() & (~hash_mask_in_place);
225 // tmp |= ((hash & hash_mask) << hash_shift);
226 // return (markOop)tmp;
227 // }
228 // it is only used to be stored into BasicLock as the
229 // indicator that the lock is using heavyweight monitor
230 // static markOop unused_mark() {
231 // return (markOop) marked_value;
232 // }
233 // // the following two functions create the markOop to be
234 // // stored into object header, it encodes monitor info
235 // static markOop encode(BasicLock* lock) {
236 // return (markOop) lock;
237 // }
238 // static markOop encode(ObjectMonitor* monitor) {
239 // intptr_t tmp = (intptr_t) monitor;
240 // return (markOop) (tmp | monitor_value);
241 // }
242 // used for alignment-based marking to reuse the busy state to encode pointers
243 // (see markOop_alignment.hpp)
244 // markOop clear_lock_bits() { return markOop(value() & ~lock_mask_in_place); }
245 //
246 // // age operations
247 // markOop set_marked() { return markOop((value() & ~lock_mask_in_place) | marked_value); }
248 //
249 public int age() { return (int) Bits.maskBitsLong(value() >> ageShift, ageMask); }
250 // markOop set_age(int v) const {
251 // assert((v & ~age_mask) == 0, "shouldn't overflow age field");
252 // return markOop((value() & ~age_mask_in_place) | (((intptr_t)v & age_mask) << age_shift));
253 // }
254 // markOop incr_age() const { return age() == max_age ? markOop(this) : set_age(age() + 1); }
255
256 // hash operations
257 public long hash() {
258 return Bits.maskBitsLong(value() >> hashShift, hashMask);
259 }
260
261 public boolean hasNoHash() {
262 return hash() == noHash;
263 }
264
265 // FIXME
266 // Prototype mark for initialization
267 // static markOop prototype() {
268 // return markOop( no_hash_in_place | no_lock_in_place );
269 // }
270
271 // Debugging
272 public void printOn(PrintStream tty) {
273 if (isLocked()) {
274 tty.print("locked(0x" +
275 Long.toHexString(value()) + ")->");
276 displacedMarkHelper().printOn(tty);
277 } else {
278 if (Assert.ASSERTS_ENABLED) {
279 Assert.that(isUnlocked(), "just checking");
280 }
281 tty.print("mark(");
282 tty.print("hash " + Long.toHexString(hash()) + ",");
283 tty.print("age " + age() + ")");
284 }
285 }
286
287 // FIXME
288 // // Prepare address of oop for placement into mark
289 // inline static markOop encode_pointer_as_mark(void* p) { return markOop(p)->set_marked(); }
290 //
291 // // Recover address of oop from encoded form used in mark
292 // inline void* decode_pointer() { return clear_lock_bits(); }
293 }