@@ -153,6 +153,80 @@ inline oop PSPromotionManager::copy_to_survivor_space(oop o) {
153
153
}
154
154
}
155
155
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
+
156
230
//
157
231
// This method is pretty bulky. It would be nice to split it up
158
232
// 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,
186
260
if (!promote_immediately) {
187
261
// Try allocating obj in to-space (unless too old)
188
262
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));
214
264
}
215
265
}
216
266
217
267
// Otherwise try allocating obj tenured
218
268
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 ) {
221
271
return oop_promotion_failed (o, test_mark);
222
272
}
223
- #endif // #ifndef PRODUCT
224
-
225
- new_obj = cast_to_oop (_old_lab.allocate (new_obj_size));
226
273
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
- }
260
274
}
261
275
262
276
assert (new_obj != nullptr , " allocation should have succeeded" );
@@ -287,25 +301,23 @@ inline oop PSPromotionManager::copy_unmarked_to_survivor_space(oop o,
287
301
// Do the size comparison first with new_obj_size, which we
288
302
// already have. Hopefully, only a few objects are larger than
289
303
// _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.
291
305
if (new_obj_size > _min_array_size_for_chunking &&
292
- new_obj-> is_objArray () &&
306
+ klass-> is_objArray_klass () &&
293
307
PSChunkLargeArrays) {
294
308
push_objArray (o, new_obj);
295
309
} else {
296
310
// we'll just push its contents
297
311
push_contents (new_obj);
298
312
299
- if (StringDedup::is_enabled () &&
300
- java_lang_String::is_instance (new_obj) &&
313
+ if (StringDedup::is_enabled_string (klass) &&
301
314
psStringDedup::is_candidate_from_evacuation (new_obj, new_obj_is_tenured)) {
302
315
_string_dedup_requests.add (o);
303
316
}
304
317
}
305
318
return new_obj;
306
319
} else {
307
320
// We lost, someone else "owns" this object.
308
-
309
321
assert (o->is_forwarded (), " Object must be forwarded if the cas failed." );
310
322
assert (o->forwardee () == forwardee, " invariant" );
311
323
0 commit comments