Skip to content

Commit 7103543

Browse files
committed
8366063: Parallel: Refactor copy_unmarked_to_survivor_space
Reviewed-by: tschatzl, iwalulya
1 parent 1feb9bd commit 7103543

File tree

2 files changed

+87
-68
lines changed

2 files changed

+87
-68
lines changed

src/hotspot/share/gc/parallel/psPromotionManager.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,13 @@ class PSPromotionManager {
113113
template<bool promote_immediately>
114114
oop copy_unmarked_to_survivor_space(oop o, markWord m);
115115

116+
inline HeapWord* allocate_in_young_gen(Klass* klass,
117+
size_t obj_size,
118+
uint age);
119+
inline HeapWord* allocate_in_old_gen(Klass* klass,
120+
size_t obj_size,
121+
uint age);
122+
116123
public:
117124
// Static
118125
static void initialize();

src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp

Lines changed: 80 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,80 @@ inline oop PSPromotionManager::copy_to_survivor_space(oop o) {
153153
}
154154
}
155155

156+
inline HeapWord* PSPromotionManager::allocate_in_young_gen(Klass* klass,
157+
size_t obj_size,
158+
uint age) {
159+
HeapWord* result = _young_lab.allocate(obj_size);
160+
if (result != nullptr) {
161+
return result;
162+
}
163+
if (_young_gen_is_full) {
164+
return nullptr;
165+
}
166+
// Do we allocate directly, or flush and refill?
167+
if (obj_size > (YoungPLABSize / 2)) {
168+
// Allocate this object directly
169+
result = young_space()->cas_allocate(obj_size);
170+
promotion_trace_event(cast_to_oop(result), klass, obj_size, age, false, nullptr);
171+
} else {
172+
// Flush and fill
173+
_young_lab.flush();
174+
175+
HeapWord* lab_base = young_space()->cas_allocate(YoungPLABSize);
176+
if (lab_base != nullptr) {
177+
_young_lab.initialize(MemRegion(lab_base, YoungPLABSize));
178+
// Try the young lab allocation again.
179+
result = _young_lab.allocate(obj_size);
180+
promotion_trace_event(cast_to_oop(result), klass, obj_size, age, false, &_young_lab);
181+
} else {
182+
_young_gen_is_full = true;
183+
}
184+
}
185+
if (result == nullptr && !_young_gen_is_full && !_young_gen_has_alloc_failure) {
186+
_young_gen_has_alloc_failure = true;
187+
}
188+
return result;
189+
}
190+
191+
inline HeapWord* PSPromotionManager::allocate_in_old_gen(Klass* klass,
192+
size_t obj_size,
193+
uint age) {
194+
#ifndef PRODUCT
195+
if (ParallelScavengeHeap::heap()->promotion_should_fail()) {
196+
return nullptr;
197+
}
198+
#endif // #ifndef PRODUCT
199+
200+
HeapWord* result = _old_lab.allocate(obj_size);
201+
if (result != nullptr) {
202+
return result;
203+
}
204+
if (_old_gen_is_full) {
205+
return nullptr;
206+
}
207+
// Do we allocate directly, or flush and refill?
208+
if (obj_size > (OldPLABSize / 2)) {
209+
// Allocate this object directly
210+
result = old_gen()->allocate(obj_size);
211+
promotion_trace_event(cast_to_oop(result), klass, obj_size, age, true, nullptr);
212+
} else {
213+
// Flush and fill
214+
_old_lab.flush();
215+
216+
HeapWord* lab_base = old_gen()->allocate(OldPLABSize);
217+
if (lab_base != nullptr) {
218+
_old_lab.initialize(MemRegion(lab_base, OldPLABSize));
219+
// Try the old lab allocation again.
220+
result = _old_lab.allocate(obj_size);
221+
promotion_trace_event(cast_to_oop(result), klass, obj_size, age, true, &_old_lab);
222+
}
223+
}
224+
if (result == nullptr) {
225+
_old_gen_is_full = true;
226+
}
227+
return result;
228+
}
229+
156230
//
157231
// This method is pretty bulky. It would be nice to split it up
158232
// into smaller submethods, but we need to be careful not to hurt
@@ -186,77 +260,17 @@ inline oop PSPromotionManager::copy_unmarked_to_survivor_space(oop o,
186260
if (!promote_immediately) {
187261
// Try allocating obj in to-space (unless too old)
188262
if (age < PSScavenge::tenuring_threshold()) {
189-
new_obj = cast_to_oop(_young_lab.allocate(new_obj_size));
190-
if (new_obj == nullptr && !_young_gen_is_full) {
191-
// Do we allocate directly, or flush and refill?
192-
if (new_obj_size > (YoungPLABSize / 2)) {
193-
// Allocate this object directly
194-
new_obj = cast_to_oop(young_space()->cas_allocate(new_obj_size));
195-
promotion_trace_event(new_obj, klass, new_obj_size, age, false, nullptr);
196-
} else {
197-
// Flush and fill
198-
_young_lab.flush();
199-
200-
HeapWord* lab_base = young_space()->cas_allocate(YoungPLABSize);
201-
if (lab_base != nullptr) {
202-
_young_lab.initialize(MemRegion(lab_base, YoungPLABSize));
203-
// Try the young lab allocation again.
204-
new_obj = cast_to_oop(_young_lab.allocate(new_obj_size));
205-
promotion_trace_event(new_obj, klass, new_obj_size, age, false, &_young_lab);
206-
} else {
207-
_young_gen_is_full = true;
208-
}
209-
}
210-
if (new_obj == nullptr && !_young_gen_is_full && !_young_gen_has_alloc_failure) {
211-
_young_gen_has_alloc_failure = true;
212-
}
213-
}
263+
new_obj = cast_to_oop(allocate_in_young_gen(klass, new_obj_size, age));
214264
}
215265
}
216266

217267
// Otherwise try allocating obj tenured
218268
if (new_obj == nullptr) {
219-
#ifndef PRODUCT
220-
if (ParallelScavengeHeap::heap()->promotion_should_fail()) {
269+
new_obj = cast_to_oop(allocate_in_old_gen(klass, new_obj_size, age));
270+
if (new_obj == nullptr) {
221271
return oop_promotion_failed(o, test_mark);
222272
}
223-
#endif // #ifndef PRODUCT
224-
225-
new_obj = cast_to_oop(_old_lab.allocate(new_obj_size));
226273
new_obj_is_tenured = true;
227-
228-
if (new_obj == nullptr) {
229-
if (!_old_gen_is_full) {
230-
// Do we allocate directly, or flush and refill?
231-
if (new_obj_size > (OldPLABSize / 2)) {
232-
// Allocate this object directly
233-
new_obj = cast_to_oop(old_gen()->allocate(new_obj_size));
234-
promotion_trace_event(new_obj, klass, new_obj_size, age, true, nullptr);
235-
} else {
236-
// Flush and fill
237-
_old_lab.flush();
238-
239-
HeapWord* lab_base = old_gen()->allocate(OldPLABSize);
240-
if(lab_base != nullptr) {
241-
_old_lab.initialize(MemRegion(lab_base, OldPLABSize));
242-
// Try the old lab allocation again.
243-
new_obj = cast_to_oop(_old_lab.allocate(new_obj_size));
244-
promotion_trace_event(new_obj, klass, new_obj_size, age, true, &_old_lab);
245-
}
246-
}
247-
}
248-
249-
// This is the promotion failed test, and code handling.
250-
// The code belongs here for two reasons. It is slightly
251-
// different than the code below, and cannot share the
252-
// CAS testing code. Keeping the code here also minimizes
253-
// the impact on the common case fast path code.
254-
255-
if (new_obj == nullptr) {
256-
_old_gen_is_full = true;
257-
return oop_promotion_failed(o, test_mark);
258-
}
259-
}
260274
}
261275

262276
assert(new_obj != nullptr, "allocation should have succeeded");
@@ -287,25 +301,23 @@ inline oop PSPromotionManager::copy_unmarked_to_survivor_space(oop o,
287301
// Do the size comparison first with new_obj_size, which we
288302
// already have. Hopefully, only a few objects are larger than
289303
// _min_array_size_for_chunking, and most of them will be arrays.
290-
// So, the is->objArray() test would be very infrequent.
304+
// So, the objArray test would be very infrequent.
291305
if (new_obj_size > _min_array_size_for_chunking &&
292-
new_obj->is_objArray() &&
306+
klass->is_objArray_klass() &&
293307
PSChunkLargeArrays) {
294308
push_objArray(o, new_obj);
295309
} else {
296310
// we'll just push its contents
297311
push_contents(new_obj);
298312

299-
if (StringDedup::is_enabled() &&
300-
java_lang_String::is_instance(new_obj) &&
313+
if (StringDedup::is_enabled_string(klass) &&
301314
psStringDedup::is_candidate_from_evacuation(new_obj, new_obj_is_tenured)) {
302315
_string_dedup_requests.add(o);
303316
}
304317
}
305318
return new_obj;
306319
} else {
307320
// We lost, someone else "owns" this object.
308-
309321
assert(o->is_forwarded(), "Object must be forwarded if the cas failed.");
310322
assert(o->forwardee() == forwardee, "invariant");
311323

0 commit comments

Comments
 (0)