Mercurial > hg > truffle
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 } |