53 |
55 |
54 MarkSweep::MarkAndPushClosure MarkSweep::mark_and_push_closure; |
56 MarkSweep::MarkAndPushClosure MarkSweep::mark_and_push_closure; |
55 CLDToOopClosure MarkSweep::follow_cld_closure(&mark_and_push_closure); |
57 CLDToOopClosure MarkSweep::follow_cld_closure(&mark_and_push_closure); |
56 CLDToOopClosure MarkSweep::adjust_cld_closure(&adjust_pointer_closure); |
58 CLDToOopClosure MarkSweep::adjust_cld_closure(&adjust_pointer_closure); |
57 |
59 |
58 void MarkSweep::MarkAndPushClosure::do_oop(oop* p) { mark_and_push(p); } |
60 template <typename T> |
59 void MarkSweep::MarkAndPushClosure::do_oop(narrowOop* p) { mark_and_push(p); } |
61 void MarkSweep::MarkAndPushClosure::do_oop_nv(T* p) { mark_and_push(p); } |
|
62 void MarkSweep::MarkAndPushClosure::do_oop(oop* p) { do_oop_nv(p); } |
|
63 void MarkSweep::MarkAndPushClosure::do_oop(narrowOop* p) { do_oop_nv(p); } |
60 |
64 |
61 void MarkSweep::follow_class_loader(ClassLoaderData* cld) { |
65 void MarkSweep::follow_class_loader(ClassLoaderData* cld) { |
62 MarkSweep::follow_cld_closure.do_cld(cld); |
66 MarkSweep::follow_cld_closure.do_cld(cld); |
63 } |
67 } |
64 |
68 |
|
69 void InstanceKlass::oop_ms_follow_contents(oop obj) { |
|
70 assert(obj != NULL, "can't follow the content of NULL object"); |
|
71 MarkSweep::follow_klass(obj->klass()); |
|
72 |
|
73 oop_oop_iterate_oop_maps<true>(obj, &MarkSweep::mark_and_push_closure); |
|
74 } |
|
75 |
|
76 void InstanceMirrorKlass::oop_ms_follow_contents(oop obj) { |
|
77 InstanceKlass::oop_ms_follow_contents(obj); |
|
78 |
|
79 // Follow the klass field in the mirror |
|
80 Klass* klass = java_lang_Class::as_Klass(obj); |
|
81 if (klass != NULL) { |
|
82 // An anonymous class doesn't have its own class loader, so the call |
|
83 // to follow_klass will mark and push its java mirror instead of the |
|
84 // class loader. When handling the java mirror for an anonymous class |
|
85 // we need to make sure its class loader data is claimed, this is done |
|
86 // by calling follow_class_loader explicitly. For non-anonymous classes |
|
87 // the call to follow_class_loader is made when the class loader itself |
|
88 // is handled. |
|
89 if (klass->oop_is_instance() && InstanceKlass::cast(klass)->is_anonymous()) { |
|
90 MarkSweep::follow_class_loader(klass->class_loader_data()); |
|
91 } else { |
|
92 MarkSweep::follow_klass(klass); |
|
93 } |
|
94 } else { |
|
95 // If klass is NULL then this a mirror for a primitive type. |
|
96 // We don't have to follow them, since they are handled as strong |
|
97 // roots in Universe::oops_do. |
|
98 assert(java_lang_Class::is_primitive(obj), "Sanity check"); |
|
99 } |
|
100 |
|
101 oop_oop_iterate_statics<true>(obj, &MarkSweep::mark_and_push_closure); |
|
102 } |
|
103 |
|
104 void InstanceClassLoaderKlass::oop_ms_follow_contents(oop obj) { |
|
105 InstanceKlass::oop_ms_follow_contents(obj); |
|
106 |
|
107 ClassLoaderData * const loader_data = java_lang_ClassLoader::loader_data(obj); |
|
108 |
|
109 // We must NULL check here, since the class loader |
|
110 // can be found before the loader data has been set up. |
|
111 if(loader_data != NULL) { |
|
112 MarkSweep::follow_class_loader(loader_data); |
|
113 } |
|
114 } |
|
115 |
|
116 template <class T> |
|
117 static void oop_ms_follow_contents_specialized(InstanceRefKlass* klass, oop obj) { |
|
118 T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj); |
|
119 T heap_oop = oopDesc::load_heap_oop(referent_addr); |
|
120 debug_only( |
|
121 if(TraceReferenceGC && PrintGCDetails) { |
|
122 gclog_or_tty->print_cr("InstanceRefKlass::oop_ms_follow_contents_specialized " PTR_FORMAT, p2i(obj)); |
|
123 } |
|
124 ) |
|
125 if (!oopDesc::is_null(heap_oop)) { |
|
126 oop referent = oopDesc::decode_heap_oop_not_null(heap_oop); |
|
127 if (!referent->is_gc_marked() && |
|
128 MarkSweep::ref_processor()->discover_reference(obj, klass->reference_type())) { |
|
129 // reference was discovered, referent will be traversed later |
|
130 klass->InstanceKlass::oop_ms_follow_contents(obj); |
|
131 debug_only( |
|
132 if(TraceReferenceGC && PrintGCDetails) { |
|
133 gclog_or_tty->print_cr(" Non NULL enqueued " PTR_FORMAT, p2i(obj)); |
|
134 } |
|
135 ) |
|
136 return; |
|
137 } else { |
|
138 // treat referent as normal oop |
|
139 debug_only( |
|
140 if(TraceReferenceGC && PrintGCDetails) { |
|
141 gclog_or_tty->print_cr(" Non NULL normal " PTR_FORMAT, p2i(obj)); |
|
142 } |
|
143 ) |
|
144 MarkSweep::mark_and_push(referent_addr); |
|
145 } |
|
146 } |
|
147 T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj); |
|
148 if (ReferenceProcessor::pending_list_uses_discovered_field()) { |
|
149 // Treat discovered as normal oop, if ref is not "active", |
|
150 // i.e. if next is non-NULL. |
|
151 T next_oop = oopDesc::load_heap_oop(next_addr); |
|
152 if (!oopDesc::is_null(next_oop)) { // i.e. ref is not "active" |
|
153 T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj); |
|
154 debug_only( |
|
155 if(TraceReferenceGC && PrintGCDetails) { |
|
156 gclog_or_tty->print_cr(" Process discovered as normal " |
|
157 PTR_FORMAT, p2i(discovered_addr)); |
|
158 } |
|
159 ) |
|
160 MarkSweep::mark_and_push(discovered_addr); |
|
161 } |
|
162 } else { |
|
163 #ifdef ASSERT |
|
164 // In the case of older JDKs which do not use the discovered |
|
165 // field for the pending list, an inactive ref (next != NULL) |
|
166 // must always have a NULL discovered field. |
|
167 oop next = oopDesc::load_decode_heap_oop(next_addr); |
|
168 oop discovered = java_lang_ref_Reference::discovered(obj); |
|
169 assert(oopDesc::is_null(next) || oopDesc::is_null(discovered), |
|
170 err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL discovered field", |
|
171 p2i(obj))); |
|
172 #endif |
|
173 } |
|
174 // treat next as normal oop. next is a link in the reference queue. |
|
175 debug_only( |
|
176 if(TraceReferenceGC && PrintGCDetails) { |
|
177 gclog_or_tty->print_cr(" Process next as normal " PTR_FORMAT, p2i(next_addr)); |
|
178 } |
|
179 ) |
|
180 MarkSweep::mark_and_push(next_addr); |
|
181 klass->InstanceKlass::oop_ms_follow_contents(obj); |
|
182 } |
|
183 |
|
184 void InstanceRefKlass::oop_ms_follow_contents(oop obj) { |
|
185 if (UseCompressedOops) { |
|
186 oop_ms_follow_contents_specialized<narrowOop>(this, obj); |
|
187 } else { |
|
188 oop_ms_follow_contents_specialized<oop>(this, obj); |
|
189 } |
|
190 } |
|
191 |
|
192 template <class T> |
|
193 static void oop_ms_follow_contents_specialized(oop obj, int index) { |
|
194 objArrayOop a = objArrayOop(obj); |
|
195 const size_t len = size_t(a->length()); |
|
196 const size_t beg_index = size_t(index); |
|
197 assert(beg_index < len || len == 0, "index too large"); |
|
198 |
|
199 const size_t stride = MIN2(len - beg_index, ObjArrayMarkingStride); |
|
200 const size_t end_index = beg_index + stride; |
|
201 T* const base = (T*)a->base(); |
|
202 T* const beg = base + beg_index; |
|
203 T* const end = base + end_index; |
|
204 |
|
205 // Push the non-NULL elements of the next stride on the marking stack. |
|
206 for (T* e = beg; e < end; e++) { |
|
207 MarkSweep::mark_and_push<T>(e); |
|
208 } |
|
209 |
|
210 if (end_index < len) { |
|
211 MarkSweep::push_objarray(a, end_index); // Push the continuation. |
|
212 } |
|
213 } |
|
214 |
|
215 void ObjArrayKlass::oop_ms_follow_contents(oop obj) { |
|
216 assert (obj->is_array(), "obj must be array"); |
|
217 MarkSweep::follow_klass(this); |
|
218 if (UseCompressedOops) { |
|
219 oop_ms_follow_contents_specialized<narrowOop>(obj, 0); |
|
220 } else { |
|
221 oop_ms_follow_contents_specialized<oop>(obj, 0); |
|
222 } |
|
223 } |
|
224 |
|
225 void TypeArrayKlass::oop_ms_follow_contents(oop obj) { |
|
226 assert(obj->is_typeArray(),"must be a type array"); |
|
227 // Performance tweak: We skip iterating over the klass pointer since we |
|
228 // know that Universe::TypeArrayKlass never moves. |
|
229 } |
|
230 |
65 void MarkSweep::follow_array(objArrayOop array, int index) { |
231 void MarkSweep::follow_array(objArrayOop array, int index) { |
66 ObjArrayKlass* k = (ObjArrayKlass*)array->klass(); |
232 if (UseCompressedOops) { |
67 k->oop_follow_contents(array, index); |
233 oop_ms_follow_contents_specialized<narrowOop>(array, index); |
|
234 } else { |
|
235 oop_ms_follow_contents_specialized<oop>(array, index); |
|
236 } |
68 } |
237 } |
69 |
238 |
70 void MarkSweep::follow_stack() { |
239 void MarkSweep::follow_stack() { |
71 do { |
240 do { |
72 while (!_marking_stack.is_empty()) { |
241 while (!_marking_stack.is_empty()) { |
173 if (TraceMarkSweep) |
344 if (TraceMarkSweep) |
174 gclog_or_tty->print("%s", msg); |
345 gclog_or_tty->print("%s", msg); |
175 } |
346 } |
176 |
347 |
177 #endif |
348 #endif |
|
349 |
|
350 int InstanceKlass::oop_ms_adjust_pointers(oop obj) { |
|
351 int size = size_helper(); |
|
352 oop_oop_iterate_oop_maps<true>(obj, &MarkSweep::adjust_pointer_closure); |
|
353 return size; |
|
354 } |
|
355 |
|
356 int InstanceMirrorKlass::oop_ms_adjust_pointers(oop obj) { |
|
357 int size = oop_size(obj); |
|
358 InstanceKlass::oop_ms_adjust_pointers(obj); |
|
359 |
|
360 oop_oop_iterate_statics<true>(obj, &MarkSweep::adjust_pointer_closure); |
|
361 return size; |
|
362 } |
|
363 |
|
364 int InstanceClassLoaderKlass::oop_ms_adjust_pointers(oop obj) { |
|
365 return InstanceKlass::oop_ms_adjust_pointers(obj); |
|
366 } |
|
367 |
|
368 #ifdef ASSERT |
|
369 template <class T> static void trace_reference_gc(const char *s, oop obj, |
|
370 T* referent_addr, |
|
371 T* next_addr, |
|
372 T* discovered_addr) { |
|
373 if(TraceReferenceGC && PrintGCDetails) { |
|
374 gclog_or_tty->print_cr("%s obj " PTR_FORMAT, s, p2i(obj)); |
|
375 gclog_or_tty->print_cr(" referent_addr/* " PTR_FORMAT " / " |
|
376 PTR_FORMAT, p2i(referent_addr), |
|
377 p2i(referent_addr ? |
|
378 (address)oopDesc::load_decode_heap_oop(referent_addr) : NULL)); |
|
379 gclog_or_tty->print_cr(" next_addr/* " PTR_FORMAT " / " |
|
380 PTR_FORMAT, p2i(next_addr), |
|
381 p2i(next_addr ? (address)oopDesc::load_decode_heap_oop(next_addr) : NULL)); |
|
382 gclog_or_tty->print_cr(" discovered_addr/* " PTR_FORMAT " / " |
|
383 PTR_FORMAT, p2i(discovered_addr), |
|
384 p2i(discovered_addr ? |
|
385 (address)oopDesc::load_decode_heap_oop(discovered_addr) : NULL)); |
|
386 } |
|
387 } |
|
388 #endif |
|
389 |
|
390 template <class T> void static adjust_object_specialized(oop obj) { |
|
391 T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj); |
|
392 MarkSweep::adjust_pointer(referent_addr); |
|
393 T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj); |
|
394 MarkSweep::adjust_pointer(next_addr); |
|
395 T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj); |
|
396 MarkSweep::adjust_pointer(discovered_addr); |
|
397 debug_only(trace_reference_gc("InstanceRefKlass::oop_ms_adjust_pointers", obj, |
|
398 referent_addr, next_addr, discovered_addr);) |
|
399 } |
|
400 |
|
401 int InstanceRefKlass::oop_ms_adjust_pointers(oop obj) { |
|
402 int size = size_helper(); |
|
403 InstanceKlass::oop_ms_adjust_pointers(obj); |
|
404 |
|
405 if (UseCompressedOops) { |
|
406 adjust_object_specialized<narrowOop>(obj); |
|
407 } else { |
|
408 adjust_object_specialized<oop>(obj); |
|
409 } |
|
410 return size; |
|
411 } |
|
412 |
|
413 int ObjArrayKlass::oop_ms_adjust_pointers(oop obj) { |
|
414 assert(obj->is_objArray(), "obj must be obj array"); |
|
415 objArrayOop a = objArrayOop(obj); |
|
416 // Get size before changing pointers. |
|
417 // Don't call size() or oop_size() since that is a virtual call. |
|
418 int size = a->object_size(); |
|
419 oop_oop_iterate_elements<true>(a, &MarkSweep::adjust_pointer_closure); |
|
420 return size; |
|
421 } |
|
422 |
|
423 int TypeArrayKlass::oop_ms_adjust_pointers(oop obj) { |
|
424 assert(obj->is_typeArray(), "must be a type array"); |
|
425 typeArrayOop t = typeArrayOop(obj); |
|
426 // Performance tweak: We skip iterating over the klass pointer since we |
|
427 // know that Universe::TypeArrayKlass never moves. |
|
428 return t->object_size(); |
|
429 } |