93 if (oops.length() != _oops_count) {
94 if (_oops != NULL) {
95 FREE_C_HEAP_ARRAY(oop*, _oops);
96 _oops = NULL;
97 }
98
99 _oops_count = oops.length();
100 if (_oops_count > 0) {
101 _oops = NEW_C_HEAP_ARRAY(oop*, _oops_count, mtGC);
102 }
103 }
104
105 for (int index = 0; index < _oops_count; index ++) {
106 _oops[index] = oops.at(index);
107 }
108 _has_non_immed_oops = non_immediate_oops;
109
110 assert_same_oops();
111 }
112
113 void ShenandoahNMethod::oops_do(OopClosure* oops, bool fix_relocations) {
114 for (int c = 0; c < _oops_count; c ++) {
115 oops->do_oop(_oops[c]);
116 }
117
118 oop* const begin = _nm->oops_begin();
119 oop* const end = _nm->oops_end();
120 for (oop* p = begin; p < end; p++) {
121 if (*p != Universe::non_oop_word()) {
122 oops->do_oop(p);
123 }
124 }
125
126 if (fix_relocations && _has_non_immed_oops) {
127 _nm->fix_oop_relocations();
128 }
129 }
130
131 void ShenandoahNMethod::detect_reloc_oops(nmethod* nm, GrowableArray<oop*>& oops, bool& has_non_immed_oops) {
132 has_non_immed_oops = false;
133 // Find all oops relocations
134 RelocIterator iter(nm);
135 while (iter.next()) {
136 if (iter.type() != relocInfo::oop_type) {
137 // Not an oop
138 continue;
139 }
140
141 oop_Relocation* r = iter.oop_reloc();
142 if (!r->oop_is_immediate()) {
143 // Non-immediate oop found
144 has_non_immed_oops = true;
145 continue;
146 }
147
148 oop value = r->oop_value();
149 if (value != NULL) {
150 oop* addr = r->oop_addr();
198 ShouldNotReachHere();
199 }
200 };
201
202 void ShenandoahNMethod::heal_nmethod(nmethod* nm) {
203 ShenandoahNMethod* data = gc_data(nm);
204 assert(data != NULL, "Sanity");
205 assert(data->lock()->owned_by_self(), "Must hold the lock");
206
207 ShenandoahHeap* const heap = ShenandoahHeap::heap();
208 if (heap->is_concurrent_mark_in_progress()) {
209 if (heap->has_forwarded_objects()) {
210 ShenandoahKeepNMethodMetadataAliveClosure<true> cl;
211 data->oops_do(&cl);
212 } else {
213 ShenandoahKeepNMethodMetadataAliveClosure<false> cl;
214 data->oops_do(&cl);
215 }
216 } else if (heap->is_concurrent_weak_root_in_progress()) {
217 ShenandoahEvacOOMScope evac_scope;
218 ShenandoahEvacuateUpdateRootsClosure<> cl;
219 data->oops_do(&cl, true /*fix relocation*/);
220 } else {
221 // There is possibility that GC is cancelled when it arrives final mark.
222 // In this case, concurrent root phase is skipped and degenerated GC should be
223 // followed, where nmethods are disarmed.
224 assert(heap->cancelled_gc(), "What else?");
225 }
226 }
227
228 #ifdef ASSERT
229 void ShenandoahNMethod::assert_alive_and_correct() {
230 assert(_nm->is_alive(), "only alive nmethods here");
231 ShenandoahHeap* heap = ShenandoahHeap::heap();
232 for (int c = 0; c < _oops_count; c++) {
233 oop *loc = _oops[c];
234 assert(_nm->code_contains((address) loc) || _nm->oops_contains(loc), "nmethod should contain the oop*");
235 oop o = RawAccess<>::oop_load(loc);
236 shenandoah_assert_correct_except(loc, o, o == NULL || heap->is_full_gc_move_in_progress());
237 }
238
239 oop* const begin = _nm->oops_begin();
|
93 if (oops.length() != _oops_count) {
94 if (_oops != NULL) {
95 FREE_C_HEAP_ARRAY(oop*, _oops);
96 _oops = NULL;
97 }
98
99 _oops_count = oops.length();
100 if (_oops_count > 0) {
101 _oops = NEW_C_HEAP_ARRAY(oop*, _oops_count, mtGC);
102 }
103 }
104
105 for (int index = 0; index < _oops_count; index ++) {
106 _oops[index] = oops.at(index);
107 }
108 _has_non_immed_oops = non_immediate_oops;
109
110 assert_same_oops();
111 }
112
113 void ShenandoahNMethod::detect_reloc_oops(nmethod* nm, GrowableArray<oop*>& oops, bool& has_non_immed_oops) {
114 has_non_immed_oops = false;
115 // Find all oops relocations
116 RelocIterator iter(nm);
117 while (iter.next()) {
118 if (iter.type() != relocInfo::oop_type) {
119 // Not an oop
120 continue;
121 }
122
123 oop_Relocation* r = iter.oop_reloc();
124 if (!r->oop_is_immediate()) {
125 // Non-immediate oop found
126 has_non_immed_oops = true;
127 continue;
128 }
129
130 oop value = r->oop_value();
131 if (value != NULL) {
132 oop* addr = r->oop_addr();
180 ShouldNotReachHere();
181 }
182 };
183
184 void ShenandoahNMethod::heal_nmethod(nmethod* nm) {
185 ShenandoahNMethod* data = gc_data(nm);
186 assert(data != NULL, "Sanity");
187 assert(data->lock()->owned_by_self(), "Must hold the lock");
188
189 ShenandoahHeap* const heap = ShenandoahHeap::heap();
190 if (heap->is_concurrent_mark_in_progress()) {
191 if (heap->has_forwarded_objects()) {
192 ShenandoahKeepNMethodMetadataAliveClosure<true> cl;
193 data->oops_do(&cl);
194 } else {
195 ShenandoahKeepNMethodMetadataAliveClosure<false> cl;
196 data->oops_do(&cl);
197 }
198 } else if (heap->is_concurrent_weak_root_in_progress()) {
199 ShenandoahEvacOOMScope evac_scope;
200 heal_nmethod_metadata(data);
201 } else {
202 // There is possibility that GC is cancelled when it arrives final mark.
203 // In this case, concurrent root phase is skipped and degenerated GC should be
204 // followed, where nmethods are disarmed.
205 assert(heap->cancelled_gc(), "What else?");
206 }
207 }
208
209 #ifdef ASSERT
210 void ShenandoahNMethod::assert_alive_and_correct() {
211 assert(_nm->is_alive(), "only alive nmethods here");
212 ShenandoahHeap* heap = ShenandoahHeap::heap();
213 for (int c = 0; c < _oops_count; c++) {
214 oop *loc = _oops[c];
215 assert(_nm->code_contains((address) loc) || _nm->oops_contains(loc), "nmethod should contain the oop*");
216 oop o = RawAccess<>::oop_load(loc);
217 shenandoah_assert_correct_except(loc, o, o == NULL || heap->is_full_gc_move_in_progress());
218 }
219
220 oop* const begin = _nm->oops_begin();
|