|
1 /* |
|
2 * Copyright 2005-2007 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 // |
|
26 // psPromotionManager is used by a single thread to manage object survival |
|
27 // during a scavenge. The promotion manager contains thread local data only. |
|
28 // |
|
29 // NOTE! Be carefull when allocating the stacks on cheap. If you are going |
|
30 // to use a promotion manager in more than one thread, the stacks MUST be |
|
31 // on cheap. This can lead to memory leaks, though, as they are not auto |
|
32 // deallocated. |
|
33 // |
|
34 // FIX ME FIX ME Add a destructor, and don't rely on the user to drain/flush/deallocate! |
|
35 // |
|
36 |
|
37 // Move to some global location |
|
38 #define HAS_BEEN_MOVED 0x1501d01d |
|
39 // End move to some global location |
|
40 |
|
41 |
|
42 class MutableSpace; |
|
43 class PSOldGen; |
|
44 class ParCompactionManager; |
|
45 class ObjectStartArray; |
|
46 class ParallelCompactData; |
|
47 class ParMarkBitMap; |
|
48 |
|
49 // Move to it's own file if this works out. |
|
50 |
|
51 class ParCompactionManager : public CHeapObj { |
|
52 friend class ParallelTaskTerminator; |
|
53 friend class ParMarkBitMap; |
|
54 friend class PSParallelCompact; |
|
55 friend class StealChunkCompactionTask; |
|
56 friend class UpdateAndFillClosure; |
|
57 friend class RefProcTaskExecutor; |
|
58 |
|
59 public: |
|
60 |
|
61 // ------------------------ Don't putback if not needed |
|
62 // Actions that the compaction manager should take. |
|
63 enum Action { |
|
64 Update, |
|
65 Copy, |
|
66 UpdateAndCopy, |
|
67 CopyAndUpdate, |
|
68 VerifyUpdate, |
|
69 ResetObjects, |
|
70 NotValid |
|
71 }; |
|
72 // ------------------------ End don't putback if not needed |
|
73 |
|
74 private: |
|
75 static ParCompactionManager** _manager_array; |
|
76 static OopTaskQueueSet* _stack_array; |
|
77 static ObjectStartArray* _start_array; |
|
78 static ChunkTaskQueueSet* _chunk_array; |
|
79 static PSOldGen* _old_gen; |
|
80 |
|
81 OopTaskQueue _marking_stack; |
|
82 GrowableArray<oop>* _overflow_stack; |
|
83 // Is there a way to reuse the _marking_stack for the |
|
84 // saving empty chunks? For now just create a different |
|
85 // type of TaskQueue. |
|
86 |
|
87 #ifdef USE_ChunkTaskQueueWithOverflow |
|
88 ChunkTaskQueueWithOverflow _chunk_stack; |
|
89 #else |
|
90 ChunkTaskQueue _chunk_stack; |
|
91 GrowableArray<size_t>* _chunk_overflow_stack; |
|
92 #endif |
|
93 |
|
94 #if 1 // does this happen enough to need a per thread stack? |
|
95 GrowableArray<Klass*>* _revisit_klass_stack; |
|
96 #endif |
|
97 static ParMarkBitMap* _mark_bitmap; |
|
98 |
|
99 Action _action; |
|
100 |
|
101 static PSOldGen* old_gen() { return _old_gen; } |
|
102 static ObjectStartArray* start_array() { return _start_array; } |
|
103 static OopTaskQueueSet* stack_array() { return _stack_array; } |
|
104 |
|
105 static void initialize(ParMarkBitMap* mbm); |
|
106 |
|
107 protected: |
|
108 // Array of tasks. Needed by the ParallelTaskTerminator. |
|
109 static ChunkTaskQueueSet* chunk_array() { return _chunk_array; } |
|
110 |
|
111 OopTaskQueue* marking_stack() { return &_marking_stack; } |
|
112 GrowableArray<oop>* overflow_stack() { return _overflow_stack; } |
|
113 #ifdef USE_ChunkTaskQueueWithOverflow |
|
114 ChunkTaskQueueWithOverflow* chunk_stack() { return &_chunk_stack; } |
|
115 #else |
|
116 ChunkTaskQueue* chunk_stack() { return &_chunk_stack; } |
|
117 GrowableArray<size_t>* chunk_overflow_stack() { return _chunk_overflow_stack; } |
|
118 #endif |
|
119 |
|
120 // Pushes onto the marking stack. If the marking stack is full, |
|
121 // pushes onto the overflow stack. |
|
122 void stack_push(oop obj); |
|
123 // Do not implement an equivalent stack_pop. Deal with the |
|
124 // marking stack and overflow stack directly. |
|
125 |
|
126 // Pushes onto the chunk stack. If the chunk stack is full, |
|
127 // pushes onto the chunk overflow stack. |
|
128 void chunk_stack_push(size_t chunk_index); |
|
129 public: |
|
130 |
|
131 Action action() { return _action; } |
|
132 void set_action(Action v) { _action = v; } |
|
133 |
|
134 inline static ParCompactionManager* manager_array(int index); |
|
135 |
|
136 ParCompactionManager(); |
|
137 ~ParCompactionManager(); |
|
138 |
|
139 void allocate_stacks(); |
|
140 void deallocate_stacks(); |
|
141 ParMarkBitMap* mark_bitmap() { return _mark_bitmap; } |
|
142 |
|
143 // Take actions in preparation for a compaction. |
|
144 static void reset(); |
|
145 |
|
146 // void drain_stacks(); |
|
147 |
|
148 bool should_update(); |
|
149 bool should_copy(); |
|
150 bool should_verify_only(); |
|
151 bool should_reset_only(); |
|
152 |
|
153 #if 1 |
|
154 // Probably stays as a growable array |
|
155 GrowableArray<Klass*>* revisit_klass_stack() { return _revisit_klass_stack; } |
|
156 #endif |
|
157 |
|
158 // Save oop for later processing. Must not fail. |
|
159 void save_for_scanning(oop m); |
|
160 // Get a oop for scanning. If returns null, no oop were found. |
|
161 oop retrieve_for_scanning(); |
|
162 |
|
163 // Save chunk for later processing. Must not fail. |
|
164 void save_for_processing(size_t chunk_index); |
|
165 // Get a chunk for processing. If returns null, no chunk were found. |
|
166 bool retrieve_for_processing(size_t& chunk_index); |
|
167 |
|
168 // Access function for compaction managers |
|
169 static ParCompactionManager* gc_thread_compaction_manager(int index); |
|
170 |
|
171 static bool steal(int queue_num, int* seed, Task& t) { |
|
172 return stack_array()->steal(queue_num, seed, t); |
|
173 } |
|
174 |
|
175 static bool steal(int queue_num, int* seed, ChunkTask& t) { |
|
176 return chunk_array()->steal(queue_num, seed, t); |
|
177 } |
|
178 |
|
179 // Process tasks remaining on any stack |
|
180 void drain_marking_stacks(OopClosure *blk); |
|
181 |
|
182 // Process tasks remaining on any stack |
|
183 void drain_chunk_stacks(); |
|
184 |
|
185 // Process tasks remaining on any stack |
|
186 void drain_chunk_overflow_stack(); |
|
187 |
|
188 // Debugging support |
|
189 #ifdef ASSERT |
|
190 bool stacks_have_been_allocated(); |
|
191 #endif |
|
192 }; |
|
193 |
|
194 inline ParCompactionManager* ParCompactionManager::manager_array(int index) { |
|
195 assert(_manager_array != NULL, "access of NULL manager_array"); |
|
196 assert(index >= 0 && index <= (int)ParallelGCThreads, |
|
197 "out of range manager_array access"); |
|
198 return _manager_array[index]; |
|
199 } |