Mercurial > hg > graal-jvmci-8
annotate src/share/vm/runtime/vm_operations.hpp @ 1716:be3f9c242c9d
6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
Summary: GC workers now recognize an intermediate transient state of blocks which are allocated but have not yet completed initialization. blk_start() calls do not attempt to determine the size of a block in the transient state, rather waiting for the block to become initialized so that it is safe to query its size. Audited and ensured the order of initialization of object fields (klass, free bit and size) to respect block state transition protocol. Also included some new assertion checking code enabled in debug mode.
Reviewed-by: chrisphi, johnc, poonam
author | ysr |
---|---|
date | Mon, 16 Aug 2010 15:58:42 -0700 |
parents | c18cbe5936b8 |
children | ce6848d0666d |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1202
diff
changeset
|
2 * Copyright (c) 1997, 2009, 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:
1202
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1202
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:
1202
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 // The following classes are used for operations | |
26 // initiated by a Java thread but that must | |
27 // take place in the VMThread. | |
28 | |
29 #define VM_OP_ENUM(type) VMOp_##type, | |
30 | |
31 // Note: When new VM_XXX comes up, add 'XXX' to the template table. | |
32 #define VM_OPS_DO(template) \ | |
33 template(Dummy) \ | |
34 template(ThreadStop) \ | |
35 template(ThreadDump) \ | |
36 template(PrintThreads) \ | |
37 template(FindDeadlocks) \ | |
38 template(ForceSafepoint) \ | |
39 template(ForceAsyncSafepoint) \ | |
40 template(Deoptimize) \ | |
41 template(DeoptimizeFrame) \ | |
42 template(DeoptimizeAll) \ | |
43 template(ZombieAll) \ | |
1202 | 44 template(HandleFullCodeCache) \ |
0 | 45 template(Verify) \ |
46 template(PrintJNI) \ | |
47 template(HeapDumper) \ | |
48 template(DeoptimizeTheWorld) \ | |
49 template(GC_HeapInspection) \ | |
50 template(GenCollectFull) \ | |
51 template(GenCollectFullConcurrent) \ | |
52 template(GenCollectForAllocation) \ | |
139
c0492d52d55b
6539517: CR 6186200 should be extended to perm gen allocation to prevent spurious OOM's from perm gen
apetrusenko
parents:
0
diff
changeset
|
53 template(GenCollectForPermanentAllocation) \ |
0 | 54 template(ParallelGCFailedAllocation) \ |
55 template(ParallelGCFailedPermanentAllocation) \ | |
56 template(ParallelGCSystemGC) \ | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
139
diff
changeset
|
57 template(CGC_Operation) \ |
0 | 58 template(CMS_Initial_Mark) \ |
59 template(CMS_Final_Remark) \ | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
139
diff
changeset
|
60 template(G1CollectFull) \ |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
139
diff
changeset
|
61 template(G1CollectForAllocation) \ |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
139
diff
changeset
|
62 template(G1IncCollectionPause) \ |
0 | 63 template(EnableBiasedLocking) \ |
64 template(RevokeBias) \ | |
65 template(BulkRevokeBias) \ | |
66 template(PopulateDumpSharedSpace) \ | |
67 template(JNIFunctionTableCopier) \ | |
68 template(RedefineClasses) \ | |
69 template(GetOwnedMonitorInfo) \ | |
70 template(GetObjectMonitorUsage) \ | |
71 template(GetCurrentContendedMonitor) \ | |
72 template(GetStackTrace) \ | |
73 template(GetMultipleStackTraces) \ | |
74 template(GetAllStackTraces) \ | |
75 template(GetThreadListStackTraces) \ | |
76 template(GetFrameCount) \ | |
77 template(GetFrameLocation) \ | |
78 template(ChangeBreakpoints) \ | |
79 template(GetOrSetLocal) \ | |
80 template(GetCurrentLocation) \ | |
81 template(EnterInterpOnlyMode) \ | |
82 template(ChangeSingleStep) \ | |
83 template(HeapWalkOperation) \ | |
84 template(HeapIterateOperation) \ | |
85 template(ReportJavaOutOfMemory) \ | |
86 template(Exit) \ | |
87 | |
88 class VM_Operation: public CHeapObj { | |
89 public: | |
90 enum Mode { | |
91 _safepoint, // blocking, safepoint, vm_op C-heap allocated | |
92 _no_safepoint, // blocking, no safepoint, vm_op C-Heap allocated | |
93 _concurrent, // non-blocking, no safepoint, vm_op C-Heap allocated | |
94 _async_safepoint // non-blocking, safepoint, vm_op C-Heap allocated | |
95 }; | |
96 | |
97 enum VMOp_Type { | |
98 VM_OPS_DO(VM_OP_ENUM) | |
99 VMOp_Terminating | |
100 }; | |
101 | |
102 private: | |
103 Thread* _calling_thread; | |
104 ThreadPriority _priority; | |
105 long _timestamp; | |
106 VM_Operation* _next; | |
107 VM_Operation* _prev; | |
108 | |
109 // The VM operation name array | |
110 static const char* _names[]; | |
111 | |
112 public: | |
113 VM_Operation() { _calling_thread = NULL; _next = NULL; _prev = NULL; } | |
114 virtual ~VM_Operation() {} | |
115 | |
116 // VM operation support (used by VM thread) | |
117 Thread* calling_thread() const { return _calling_thread; } | |
118 ThreadPriority priority() { return _priority; } | |
119 void set_calling_thread(Thread* thread, ThreadPriority priority); | |
120 | |
121 long timestamp() const { return _timestamp; } | |
122 void set_timestamp(long timestamp) { _timestamp = timestamp; } | |
123 | |
124 // Called by VM thread - does in turn invoke doit(). Do not override this | |
125 void evaluate(); | |
126 | |
127 // evaluate() is called by the VMThread and in turn calls doit(). | |
128 // If the thread invoking VMThread::execute((VM_Operation*) is a JavaThread, | |
129 // doit_prologue() is called in that thread before transferring control to | |
130 // the VMThread. | |
131 // If doit_prologue() returns true the VM operation will proceed, and | |
132 // doit_epilogue() will be called by the JavaThread once the VM operation | |
133 // completes. If doit_prologue() returns false the VM operation is cancelled. | |
134 virtual void doit() = 0; | |
135 virtual bool doit_prologue() { return true; }; | |
136 virtual void doit_epilogue() {}; // Note: Not called if mode is: _concurrent | |
137 | |
138 // Type test | |
139 virtual bool is_methodCompiler() const { return false; } | |
140 | |
141 // Linking | |
142 VM_Operation *next() const { return _next; } | |
143 VM_Operation *prev() const { return _prev; } | |
144 void set_next(VM_Operation *next) { _next = next; } | |
145 void set_prev(VM_Operation *prev) { _prev = prev; } | |
146 | |
147 // Configuration. Override these appropriatly in subclasses. | |
148 virtual VMOp_Type type() const = 0; | |
149 virtual Mode evaluation_mode() const { return _safepoint; } | |
150 virtual bool allow_nested_vm_operations() const { return false; } | |
151 virtual bool is_cheap_allocated() const { return false; } | |
152 virtual void oops_do(OopClosure* f) { /* do nothing */ }; | |
153 | |
154 // CAUTION: <don't hang yourself with following rope> | |
155 // If you override these methods, make sure that the evaluation | |
156 // of these methods is race-free and non-blocking, since these | |
157 // methods may be evaluated either by the mutators or by the | |
158 // vm thread, either concurrently with mutators or with the mutators | |
159 // stopped. In other words, taking locks is verboten, and if there | |
160 // are any races in evaluating the conditions, they'd better be benign. | |
161 virtual bool evaluate_at_safepoint() const { | |
162 return evaluation_mode() == _safepoint || | |
163 evaluation_mode() == _async_safepoint; | |
164 } | |
165 virtual bool evaluate_concurrently() const { | |
166 return evaluation_mode() == _concurrent || | |
167 evaluation_mode() == _async_safepoint; | |
168 } | |
169 | |
170 // Debugging | |
171 void print_on_error(outputStream* st) const; | |
172 const char* name() const { return _names[type()]; } | |
173 static const char* name(int type) { | |
174 assert(type >= 0 && type < VMOp_Terminating, "invalid VM operation type"); | |
175 return _names[type]; | |
176 } | |
177 #ifndef PRODUCT | |
178 void print_on(outputStream* st) const { print_on_error(st); } | |
179 #endif | |
180 }; | |
181 | |
182 class VM_ThreadStop: public VM_Operation { | |
183 private: | |
184 oop _thread; // The Thread that the Throwable is thrown against | |
185 oop _throwable; // The Throwable thrown at the target Thread | |
186 public: | |
187 // All oops are passed as JNI handles, since there is no guarantee that a GC might happen before the | |
188 // VM operation is executed. | |
189 VM_ThreadStop(oop thread, oop throwable) { | |
190 _thread = thread; | |
191 _throwable = throwable; | |
192 } | |
193 VMOp_Type type() const { return VMOp_ThreadStop; } | |
194 oop target_thread() const { return _thread; } | |
195 oop throwable() const { return _throwable;} | |
196 void doit(); | |
197 // We deoptimize if top-most frame is compiled - this might require a C2I adapter to be generated | |
198 bool allow_nested_vm_operations() const { return true; } | |
199 Mode evaluation_mode() const { return _async_safepoint; } | |
200 bool is_cheap_allocated() const { return true; } | |
201 | |
202 // GC support | |
203 void oops_do(OopClosure* f) { | |
204 f->do_oop(&_thread); f->do_oop(&_throwable); | |
205 } | |
206 }; | |
207 | |
208 // dummy vm op, evaluated just to force a safepoint | |
209 class VM_ForceSafepoint: public VM_Operation { | |
210 public: | |
211 VM_ForceSafepoint() {} | |
212 void doit() {} | |
213 VMOp_Type type() const { return VMOp_ForceSafepoint; } | |
214 }; | |
215 | |
216 // dummy vm op, evaluated just to force a safepoint | |
217 class VM_ForceAsyncSafepoint: public VM_Operation { | |
218 public: | |
219 VM_ForceAsyncSafepoint() {} | |
220 void doit() {} | |
221 VMOp_Type type() const { return VMOp_ForceAsyncSafepoint; } | |
222 Mode evaluation_mode() const { return _async_safepoint; } | |
223 bool is_cheap_allocated() const { return true; } | |
224 }; | |
225 | |
226 class VM_Deoptimize: public VM_Operation { | |
227 public: | |
228 VM_Deoptimize() {} | |
229 VMOp_Type type() const { return VMOp_Deoptimize; } | |
230 void doit(); | |
231 bool allow_nested_vm_operations() const { return true; } | |
232 }; | |
233 | |
234 class VM_DeoptimizeFrame: public VM_Operation { | |
235 private: | |
236 JavaThread* _thread; | |
237 intptr_t* _id; | |
238 public: | |
239 VM_DeoptimizeFrame(JavaThread* thread, intptr_t* id); | |
240 VMOp_Type type() const { return VMOp_DeoptimizeFrame; } | |
241 void doit(); | |
242 bool allow_nested_vm_operations() const { return true; } | |
243 }; | |
244 | |
1202 | 245 class VM_HandleFullCodeCache: public VM_Operation { |
246 private: | |
247 bool _is_full; | |
248 public: | |
249 VM_HandleFullCodeCache(bool is_full) { _is_full = is_full; } | |
250 VMOp_Type type() const { return VMOp_HandleFullCodeCache; } | |
251 void doit(); | |
252 bool allow_nested_vm_operations() const { return true; } | |
253 }; | |
254 | |
0 | 255 #ifndef PRODUCT |
256 class VM_DeoptimizeAll: public VM_Operation { | |
257 private: | |
258 KlassHandle _dependee; | |
259 public: | |
260 VM_DeoptimizeAll() {} | |
261 VMOp_Type type() const { return VMOp_DeoptimizeAll; } | |
262 void doit(); | |
263 bool allow_nested_vm_operations() const { return true; } | |
264 }; | |
265 | |
266 | |
267 class VM_ZombieAll: public VM_Operation { | |
268 public: | |
269 VM_ZombieAll() {} | |
270 VMOp_Type type() const { return VMOp_ZombieAll; } | |
271 void doit(); | |
272 bool allow_nested_vm_operations() const { return true; } | |
273 }; | |
274 #endif // PRODUCT | |
275 | |
276 class VM_Verify: public VM_Operation { | |
277 private: | |
278 KlassHandle _dependee; | |
279 public: | |
280 VM_Verify() {} | |
281 VMOp_Type type() const { return VMOp_Verify; } | |
282 void doit(); | |
283 }; | |
284 | |
285 | |
286 class VM_PrintThreads: public VM_Operation { | |
287 private: | |
288 outputStream* _out; | |
289 bool _print_concurrent_locks; | |
290 public: | |
291 VM_PrintThreads() { _out = tty; _print_concurrent_locks = PrintConcurrentLocks; } | |
292 VM_PrintThreads(outputStream* out, bool print_concurrent_locks) { _out = out; _print_concurrent_locks = print_concurrent_locks; } | |
293 VMOp_Type type() const { return VMOp_PrintThreads; } | |
294 void doit(); | |
295 bool doit_prologue(); | |
296 void doit_epilogue(); | |
297 }; | |
298 | |
299 class VM_PrintJNI: public VM_Operation { | |
300 private: | |
301 outputStream* _out; | |
302 public: | |
303 VM_PrintJNI() { _out = tty; } | |
304 VM_PrintJNI(outputStream* out) { _out = out; } | |
305 VMOp_Type type() const { return VMOp_PrintJNI; } | |
306 void doit(); | |
307 }; | |
308 | |
309 class DeadlockCycle; | |
310 class VM_FindDeadlocks: public VM_Operation { | |
311 private: | |
312 bool _concurrent_locks; | |
313 DeadlockCycle* _deadlocks; | |
314 outputStream* _out; | |
315 | |
316 public: | |
317 VM_FindDeadlocks(bool concurrent_locks) : _concurrent_locks(concurrent_locks), _out(NULL), _deadlocks(NULL) {}; | |
318 VM_FindDeadlocks(outputStream* st) : _concurrent_locks(true), _out(st), _deadlocks(NULL) {}; | |
319 ~VM_FindDeadlocks(); | |
320 | |
321 DeadlockCycle* result() { return _deadlocks; }; | |
322 VMOp_Type type() const { return VMOp_FindDeadlocks; } | |
323 void doit(); | |
324 bool doit_prologue(); | |
325 }; | |
326 | |
327 class ThreadDumpResult; | |
328 class ThreadSnapshot; | |
329 class ThreadConcurrentLocks; | |
330 | |
331 class VM_ThreadDump : public VM_Operation { | |
332 private: | |
333 ThreadDumpResult* _result; | |
334 int _num_threads; | |
335 GrowableArray<instanceHandle>* _threads; | |
336 int _max_depth; | |
337 bool _with_locked_monitors; | |
338 bool _with_locked_synchronizers; | |
339 | |
340 ThreadSnapshot* snapshot_thread(JavaThread* java_thread, ThreadConcurrentLocks* tcl); | |
341 | |
342 public: | |
343 VM_ThreadDump(ThreadDumpResult* result, | |
344 int max_depth, // -1 indicates entire stack | |
345 bool with_locked_monitors, | |
346 bool with_locked_synchronizers); | |
347 | |
348 VM_ThreadDump(ThreadDumpResult* result, | |
349 GrowableArray<instanceHandle>* threads, | |
350 int num_threads, // -1 indicates entire stack | |
351 int max_depth, | |
352 bool with_locked_monitors, | |
353 bool with_locked_synchronizers); | |
354 | |
355 VMOp_Type type() const { return VMOp_ThreadDump; } | |
356 void doit(); | |
357 bool doit_prologue(); | |
358 void doit_epilogue(); | |
359 }; | |
360 | |
361 | |
362 class VM_Exit: public VM_Operation { | |
363 private: | |
364 int _exit_code; | |
365 static volatile bool _vm_exited; | |
366 static Thread * _shutdown_thread; | |
367 static void wait_if_vm_exited(); | |
368 public: | |
369 VM_Exit(int exit_code) { | |
370 _exit_code = exit_code; | |
371 } | |
372 static int wait_for_threads_in_native_to_block(); | |
373 static int set_vm_exited(); | |
374 static bool vm_exited() { return _vm_exited; } | |
375 static void block_if_vm_exited() { | |
376 if (_vm_exited) { | |
377 wait_if_vm_exited(); | |
378 } | |
379 } | |
380 VMOp_Type type() const { return VMOp_Exit; } | |
381 void doit(); | |
382 }; |